summaryrefslogtreecommitdiff
path: root/boost
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2017-09-13 11:08:07 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2017-09-13 11:09:00 +0900
commitb5c87084afaef42b2d058f68091be31988a6a874 (patch)
treeadef9a65870a41181687e11d57fdf98e7629de3c /boost
parent34bd32e225e2a8a94104489b31c42e5801cc1f4a (diff)
downloadboost-b5c87084afaef42b2d058f68091be31988a6a874.tar.gz
boost-b5c87084afaef42b2d058f68091be31988a6a874.tar.bz2
boost-b5c87084afaef42b2d058f68091be31988a6a874.zip
Imported Upstream version 1.64.0upstream/1.64.0
Change-Id: Id9212edd016dd55f21172c427aa7894d1d24148b Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'boost')
-rw-r--r--boost/align.hpp9
-rw-r--r--boost/align/align.hpp9
-rw-r--r--boost/align/align_down.hpp18
-rw-r--r--boost/align/align_down_forward.hpp24
-rw-r--r--boost/align/align_up.hpp18
-rw-r--r--boost/align/align_up_forward.hpp24
-rw-r--r--boost/align/aligned_alloc.hpp9
-rw-r--r--boost/align/aligned_allocator.hpp39
-rw-r--r--boost/align/aligned_allocator_adaptor.hpp37
-rw-r--r--boost/align/aligned_allocator_adaptor_forward.hpp13
-rw-r--r--boost/align/aligned_allocator_forward.hpp13
-rw-r--r--boost/align/aligned_delete.hpp13
-rw-r--r--boost/align/aligned_delete_forward.hpp13
-rw-r--r--boost/align/alignment_of.hpp16
-rw-r--r--boost/align/alignment_of_forward.hpp13
-rw-r--r--boost/align/assume_aligned.hpp13
-rw-r--r--boost/align/detail/addressof.hpp15
-rw-r--r--boost/align/detail/align.hpp22
-rw-r--r--boost/align/detail/align_cxx11.hpp13
-rw-r--r--boost/align/detail/align_down.hpp20
-rw-r--r--boost/align/detail/align_up.hpp20
-rw-r--r--boost/align/detail/aligned_alloc.hpp34
-rw-r--r--boost/align/detail/aligned_alloc_android.hpp20
-rw-r--r--boost/align/detail/aligned_alloc_macos.hpp20
-rw-r--r--boost/align/detail/aligned_alloc_msvc.hpp20
-rw-r--r--boost/align/detail/aligned_alloc_posix.hpp20
-rw-r--r--boost/align/detail/aligned_alloc_sunos.hpp20
-rw-r--r--boost/align/detail/alignment_of.hpp19
-rw-r--r--boost/align/detail/alignment_of_clang.hpp15
-rw-r--r--boost/align/detail/alignment_of_codegear.hpp15
-rw-r--r--boost/align/detail/alignment_of_cxx11.hpp15
-rw-r--r--boost/align/detail/alignment_of_gcc.hpp15
-rw-r--r--boost/align/detail/alignment_of_msvc.hpp19
-rw-r--r--boost/align/detail/assume_aligned.hpp15
-rw-r--r--boost/align/detail/assume_aligned_clang.hpp11
-rw-r--r--boost/align/detail/assume_aligned_gcc.hpp15
-rw-r--r--boost/align/detail/assume_aligned_intel.hpp17
-rw-r--r--boost/align/detail/assume_aligned_msvc.hpp17
-rw-r--r--boost/align/detail/element_type.hpp44
-rw-r--r--boost/align/detail/integral_constant.hpp18
-rw-r--r--boost/align/detail/is_aligned.hpp26
-rw-r--r--boost/align/detail/is_alignment.hpp20
-rw-r--r--boost/align/detail/is_alignment_constant.hpp15
-rw-r--r--boost/align/detail/max_align.hpp15
-rw-r--r--boost/align/detail/max_objects.hpp15
-rw-r--r--boost/align/detail/max_size.hpp15
-rw-r--r--boost/align/detail/min_size.hpp15
-rw-r--r--boost/align/is_aligned.hpp19
-rw-r--r--boost/align/is_aligned_forward.hpp24
-rw-r--r--boost/any.hpp20
-rw-r--r--boost/archive/basic_binary_iprimitive.hpp2
-rw-r--r--boost/archive/basic_binary_oprimitive.hpp2
-rw-r--r--boost/archive/basic_text_oprimitive.hpp2
-rw-r--r--boost/archive/basic_xml_iarchive.hpp3
-rw-r--r--boost/archive/detail/iserializer.hpp11
-rw-r--r--boost/archive/detail/oserializer.hpp12
-rw-r--r--boost/archive/detail/utf8_codecvt_facet.hpp15
-rw-r--r--boost/archive/iterators/mb_from_wchar.hpp1
-rw-r--r--boost/array.hpp95
-rw-r--r--boost/asio.hpp2
-rw-r--r--boost/asio/async_result.hpp2
-rw-r--r--boost/asio/basic_datagram_socket.hpp2
-rw-r--r--boost/asio/basic_deadline_timer.hpp2
-rw-r--r--boost/asio/basic_io_object.hpp17
-rw-r--r--boost/asio/basic_raw_socket.hpp2
-rw-r--r--boost/asio/basic_seq_packet_socket.hpp2
-rw-r--r--boost/asio/basic_serial_port.hpp2
-rw-r--r--boost/asio/basic_signal_set.hpp2
-rw-r--r--boost/asio/basic_socket.hpp7
-rw-r--r--boost/asio/basic_socket_acceptor.hpp7
-rw-r--r--boost/asio/basic_socket_iostream.hpp2
-rw-r--r--boost/asio/basic_socket_streambuf.hpp2
-rw-r--r--boost/asio/basic_stream_socket.hpp2
-rw-r--r--boost/asio/basic_streambuf.hpp2
-rw-r--r--boost/asio/basic_streambuf_fwd.hpp2
-rw-r--r--boost/asio/basic_waitable_timer.hpp2
-rw-r--r--boost/asio/buffer.hpp2
-rw-r--r--boost/asio/buffered_read_stream.hpp2
-rw-r--r--boost/asio/buffered_read_stream_fwd.hpp2
-rw-r--r--boost/asio/buffered_stream.hpp2
-rw-r--r--boost/asio/buffered_stream_fwd.hpp2
-rw-r--r--boost/asio/buffered_write_stream.hpp2
-rw-r--r--boost/asio/buffered_write_stream_fwd.hpp2
-rw-r--r--boost/asio/buffers_iterator.hpp2
-rw-r--r--boost/asio/completion_condition.hpp2
-rw-r--r--boost/asio/connect.hpp2
-rw-r--r--boost/asio/coroutine.hpp2
-rw-r--r--boost/asio/datagram_socket_service.hpp8
-rw-r--r--boost/asio/deadline_timer.hpp2
-rw-r--r--boost/asio/deadline_timer_service.hpp2
-rw-r--r--boost/asio/detail/addressof.hpp2
-rw-r--r--boost/asio/detail/array.hpp2
-rw-r--r--boost/asio/detail/array_fwd.hpp2
-rw-r--r--boost/asio/detail/assert.hpp2
-rw-r--r--boost/asio/detail/atomic_count.hpp2
-rw-r--r--boost/asio/detail/base_from_completion_cond.hpp2
-rw-r--r--boost/asio/detail/bind_handler.hpp2
-rw-r--r--boost/asio/detail/buffer_resize_guard.hpp2
-rw-r--r--boost/asio/detail/buffer_sequence_adapter.hpp2
-rw-r--r--boost/asio/detail/buffered_stream_storage.hpp2
-rw-r--r--boost/asio/detail/call_stack.hpp2
-rw-r--r--boost/asio/detail/chrono_time_traits.hpp2
-rw-r--r--boost/asio/detail/completion_handler.hpp2
-rw-r--r--boost/asio/detail/config.hpp56
-rw-r--r--boost/asio/detail/consuming_buffers.hpp2
-rw-r--r--boost/asio/detail/cstdint.hpp2
-rw-r--r--boost/asio/detail/date_time_fwd.hpp2
-rw-r--r--boost/asio/detail/deadline_timer_service.hpp2
-rw-r--r--boost/asio/detail/dependent_type.hpp2
-rw-r--r--boost/asio/detail/descriptor_ops.hpp2
-rw-r--r--boost/asio/detail/descriptor_read_op.hpp2
-rw-r--r--boost/asio/detail/descriptor_write_op.hpp2
-rw-r--r--boost/asio/detail/dev_poll_reactor.hpp2
-rw-r--r--boost/asio/detail/epoll_reactor.hpp2
-rw-r--r--boost/asio/detail/event.hpp2
-rw-r--r--boost/asio/detail/eventfd_select_interrupter.hpp2
-rw-r--r--boost/asio/detail/fd_set_adapter.hpp2
-rw-r--r--boost/asio/detail/fenced_block.hpp6
-rw-r--r--boost/asio/detail/function.hpp2
-rw-r--r--boost/asio/detail/gcc_arm_fenced_block.hpp2
-rw-r--r--boost/asio/detail/gcc_hppa_fenced_block.hpp2
-rw-r--r--boost/asio/detail/gcc_sync_fenced_block.hpp2
-rw-r--r--boost/asio/detail/gcc_x86_fenced_block.hpp2
-rw-r--r--boost/asio/detail/handler_alloc_helpers.hpp2
-rw-r--r--boost/asio/detail/handler_cont_helpers.hpp2
-rw-r--r--boost/asio/detail/handler_invoke_helpers.hpp2
-rw-r--r--boost/asio/detail/handler_tracking.hpp2
-rw-r--r--boost/asio/detail/handler_type_requirements.hpp22
-rw-r--r--boost/asio/detail/hash_map.hpp8
-rw-r--r--boost/asio/detail/impl/buffer_sequence_adapter.ipp2
-rw-r--r--boost/asio/detail/impl/descriptor_ops.ipp2
-rw-r--r--boost/asio/detail/impl/dev_poll_reactor.hpp2
-rw-r--r--boost/asio/detail/impl/dev_poll_reactor.ipp2
-rw-r--r--boost/asio/detail/impl/epoll_reactor.hpp2
-rw-r--r--boost/asio/detail/impl/epoll_reactor.ipp28
-rw-r--r--boost/asio/detail/impl/eventfd_select_interrupter.ipp2
-rw-r--r--boost/asio/detail/impl/handler_tracking.ipp2
-rw-r--r--boost/asio/detail/impl/kqueue_reactor.hpp2
-rw-r--r--boost/asio/detail/impl/kqueue_reactor.ipp2
-rw-r--r--boost/asio/detail/impl/pipe_select_interrupter.ipp2
-rw-r--r--boost/asio/detail/impl/posix_event.ipp2
-rw-r--r--boost/asio/detail/impl/posix_mutex.ipp2
-rw-r--r--boost/asio/detail/impl/posix_thread.ipp2
-rw-r--r--boost/asio/detail/impl/posix_tss_ptr.ipp2
-rw-r--r--boost/asio/detail/impl/reactive_descriptor_service.ipp2
-rw-r--r--boost/asio/detail/impl/reactive_serial_port_service.ipp2
-rw-r--r--boost/asio/detail/impl/reactive_socket_service_base.ipp2
-rw-r--r--boost/asio/detail/impl/resolver_service_base.ipp2
-rw-r--r--boost/asio/detail/impl/select_reactor.hpp2
-rw-r--r--boost/asio/detail/impl/select_reactor.ipp2
-rw-r--r--boost/asio/detail/impl/service_registry.hpp2
-rw-r--r--boost/asio/detail/impl/service_registry.ipp2
-rw-r--r--boost/asio/detail/impl/signal_set_service.ipp2
-rw-r--r--boost/asio/detail/impl/socket_ops.ipp33
-rw-r--r--boost/asio/detail/impl/socket_select_interrupter.ipp2
-rw-r--r--boost/asio/detail/impl/strand_service.hpp2
-rw-r--r--boost/asio/detail/impl/strand_service.ipp2
-rw-r--r--boost/asio/detail/impl/task_io_service.hpp2
-rw-r--r--boost/asio/detail/impl/task_io_service.ipp2
-rw-r--r--boost/asio/detail/impl/throw_error.ipp2
-rw-r--r--boost/asio/detail/impl/timer_queue_ptime.ipp2
-rw-r--r--boost/asio/detail/impl/timer_queue_set.ipp2
-rw-r--r--boost/asio/detail/impl/win_event.ipp2
-rw-r--r--boost/asio/detail/impl/win_iocp_handle_service.ipp2
-rw-r--r--boost/asio/detail/impl/win_iocp_io_service.hpp2
-rw-r--r--boost/asio/detail/impl/win_iocp_io_service.ipp2
-rw-r--r--boost/asio/detail/impl/win_iocp_serial_port_service.ipp2
-rw-r--r--boost/asio/detail/impl/win_iocp_socket_service_base.ipp2
-rw-r--r--boost/asio/detail/impl/win_mutex.ipp7
-rw-r--r--boost/asio/detail/impl/win_object_handle_service.ipp2
-rw-r--r--boost/asio/detail/impl/win_static_mutex.ipp2
-rw-r--r--boost/asio/detail/impl/win_thread.ipp2
-rw-r--r--boost/asio/detail/impl/win_tss_ptr.ipp2
-rw-r--r--boost/asio/detail/impl/winrt_ssocket_service_base.ipp2
-rw-r--r--boost/asio/detail/impl/winrt_timer_scheduler.hpp2
-rw-r--r--boost/asio/detail/impl/winrt_timer_scheduler.ipp2
-rw-r--r--boost/asio/detail/impl/winsock_init.ipp2
-rw-r--r--boost/asio/detail/io_control.hpp2
-rw-r--r--boost/asio/detail/keyword_tss_ptr.hpp2
-rw-r--r--boost/asio/detail/kqueue_reactor.hpp2
-rw-r--r--boost/asio/detail/local_free_on_block_exit.hpp2
-rw-r--r--boost/asio/detail/macos_fenced_block.hpp2
-rw-r--r--boost/asio/detail/memory.hpp31
-rw-r--r--boost/asio/detail/mutex.hpp2
-rw-r--r--boost/asio/detail/noncopyable.hpp2
-rw-r--r--boost/asio/detail/null_event.hpp2
-rw-r--r--boost/asio/detail/null_fenced_block.hpp2
-rw-r--r--boost/asio/detail/null_mutex.hpp2
-rw-r--r--boost/asio/detail/null_reactor.hpp2
-rw-r--r--boost/asio/detail/null_signal_blocker.hpp2
-rw-r--r--boost/asio/detail/null_socket_service.hpp3
-rw-r--r--boost/asio/detail/null_static_mutex.hpp2
-rw-r--r--boost/asio/detail/null_thread.hpp2
-rw-r--r--boost/asio/detail/null_tss_ptr.hpp2
-rw-r--r--boost/asio/detail/object_pool.hpp2
-rw-r--r--boost/asio/detail/old_win_sdk_compat.hpp2
-rw-r--r--boost/asio/detail/op_queue.hpp2
-rw-r--r--boost/asio/detail/operation.hpp2
-rw-r--r--boost/asio/detail/pipe_select_interrupter.hpp2
-rw-r--r--boost/asio/detail/pop_options.hpp2
-rw-r--r--boost/asio/detail/posix_event.hpp2
-rw-r--r--boost/asio/detail/posix_fd_set_adapter.hpp2
-rw-r--r--boost/asio/detail/posix_mutex.hpp2
-rw-r--r--boost/asio/detail/posix_signal_blocker.hpp2
-rw-r--r--boost/asio/detail/posix_static_mutex.hpp2
-rw-r--r--boost/asio/detail/posix_thread.hpp2
-rw-r--r--boost/asio/detail/posix_tss_ptr.hpp2
-rw-r--r--boost/asio/detail/push_options.hpp2
-rw-r--r--boost/asio/detail/reactive_descriptor_service.hpp2
-rw-r--r--boost/asio/detail/reactive_null_buffers_op.hpp2
-rw-r--r--boost/asio/detail/reactive_serial_port_service.hpp2
-rw-r--r--boost/asio/detail/reactive_socket_accept_op.hpp2
-rw-r--r--boost/asio/detail/reactive_socket_connect_op.hpp2
-rw-r--r--boost/asio/detail/reactive_socket_recv_op.hpp2
-rw-r--r--boost/asio/detail/reactive_socket_recvfrom_op.hpp2
-rw-r--r--boost/asio/detail/reactive_socket_recvmsg_op.hpp2
-rw-r--r--boost/asio/detail/reactive_socket_send_op.hpp2
-rw-r--r--boost/asio/detail/reactive_socket_sendto_op.hpp2
-rw-r--r--boost/asio/detail/reactive_socket_service.hpp3
-rw-r--r--boost/asio/detail/reactive_socket_service_base.hpp2
-rw-r--r--boost/asio/detail/reactor.hpp2
-rw-r--r--boost/asio/detail/reactor_fwd.hpp2
-rw-r--r--boost/asio/detail/reactor_op.hpp2
-rw-r--r--boost/asio/detail/reactor_op_queue.hpp2
-rw-r--r--boost/asio/detail/regex_fwd.hpp2
-rw-r--r--boost/asio/detail/resolve_endpoint_op.hpp2
-rw-r--r--boost/asio/detail/resolve_op.hpp2
-rw-r--r--boost/asio/detail/resolver_service.hpp2
-rw-r--r--boost/asio/detail/resolver_service_base.hpp2
-rw-r--r--boost/asio/detail/scoped_lock.hpp2
-rw-r--r--boost/asio/detail/scoped_ptr.hpp2
-rw-r--r--boost/asio/detail/select_interrupter.hpp2
-rw-r--r--boost/asio/detail/select_reactor.hpp2
-rw-r--r--boost/asio/detail/service_registry.hpp2
-rw-r--r--boost/asio/detail/shared_ptr.hpp2
-rw-r--r--boost/asio/detail/signal_blocker.hpp2
-rw-r--r--boost/asio/detail/signal_handler.hpp2
-rw-r--r--boost/asio/detail/signal_init.hpp2
-rw-r--r--boost/asio/detail/signal_op.hpp2
-rw-r--r--boost/asio/detail/signal_set_service.hpp2
-rw-r--r--boost/asio/detail/socket_holder.hpp2
-rw-r--r--boost/asio/detail/socket_ops.hpp2
-rw-r--r--boost/asio/detail/socket_option.hpp2
-rw-r--r--boost/asio/detail/socket_select_interrupter.hpp2
-rw-r--r--boost/asio/detail/socket_types.hpp6
-rw-r--r--boost/asio/detail/solaris_fenced_block.hpp2
-rw-r--r--boost/asio/detail/static_mutex.hpp2
-rw-r--r--boost/asio/detail/std_event.hpp2
-rw-r--r--boost/asio/detail/std_fenced_block.hpp64
-rw-r--r--boost/asio/detail/std_mutex.hpp2
-rw-r--r--boost/asio/detail/std_static_mutex.hpp2
-rw-r--r--boost/asio/detail/std_thread.hpp2
-rw-r--r--boost/asio/detail/strand_service.hpp2
-rw-r--r--boost/asio/detail/task_io_service.hpp2
-rw-r--r--boost/asio/detail/task_io_service_operation.hpp2
-rw-r--r--boost/asio/detail/task_io_service_thread_info.hpp2
-rw-r--r--boost/asio/detail/thread.hpp2
-rw-r--r--boost/asio/detail/thread_info_base.hpp2
-rw-r--r--boost/asio/detail/throw_error.hpp2
-rw-r--r--boost/asio/detail/throw_exception.hpp2
-rw-r--r--boost/asio/detail/timer_queue.hpp2
-rw-r--r--boost/asio/detail/timer_queue_base.hpp2
-rw-r--r--boost/asio/detail/timer_queue_ptime.hpp2
-rw-r--r--boost/asio/detail/timer_queue_set.hpp2
-rw-r--r--boost/asio/detail/timer_scheduler.hpp2
-rw-r--r--boost/asio/detail/timer_scheduler_fwd.hpp2
-rw-r--r--boost/asio/detail/tss_ptr.hpp2
-rw-r--r--boost/asio/detail/type_traits.hpp2
-rw-r--r--boost/asio/detail/variadic_templates.hpp2
-rw-r--r--boost/asio/detail/wait_handler.hpp2
-rw-r--r--boost/asio/detail/wait_op.hpp2
-rw-r--r--boost/asio/detail/weak_ptr.hpp2
-rw-r--r--boost/asio/detail/win_event.hpp2
-rw-r--r--boost/asio/detail/win_fd_set_adapter.hpp2
-rw-r--r--boost/asio/detail/win_fenced_block.hpp2
-rw-r--r--boost/asio/detail/win_iocp_handle_read_op.hpp2
-rw-r--r--boost/asio/detail/win_iocp_handle_service.hpp2
-rw-r--r--boost/asio/detail/win_iocp_handle_write_op.hpp2
-rw-r--r--boost/asio/detail/win_iocp_io_service.hpp2
-rw-r--r--boost/asio/detail/win_iocp_null_buffers_op.hpp2
-rw-r--r--boost/asio/detail/win_iocp_operation.hpp2
-rw-r--r--boost/asio/detail/win_iocp_overlapped_op.hpp2
-rw-r--r--boost/asio/detail/win_iocp_overlapped_ptr.hpp2
-rw-r--r--boost/asio/detail/win_iocp_serial_port_service.hpp2
-rw-r--r--boost/asio/detail/win_iocp_socket_accept_op.hpp2
-rw-r--r--boost/asio/detail/win_iocp_socket_connect_op.hpp2
-rw-r--r--boost/asio/detail/win_iocp_socket_recv_op.hpp2
-rw-r--r--boost/asio/detail/win_iocp_socket_recvfrom_op.hpp2
-rw-r--r--boost/asio/detail/win_iocp_socket_recvmsg_op.hpp2
-rw-r--r--boost/asio/detail/win_iocp_socket_send_op.hpp2
-rw-r--r--boost/asio/detail/win_iocp_socket_service.hpp3
-rw-r--r--boost/asio/detail/win_iocp_socket_service_base.hpp2
-rw-r--r--boost/asio/detail/win_iocp_thread_info.hpp2
-rw-r--r--boost/asio/detail/win_mutex.hpp2
-rw-r--r--boost/asio/detail/win_object_handle_service.hpp2
-rw-r--r--boost/asio/detail/win_static_mutex.hpp2
-rw-r--r--boost/asio/detail/win_thread.hpp2
-rw-r--r--boost/asio/detail/win_tss_ptr.hpp2
-rw-r--r--boost/asio/detail/winapi_thread.hpp2
-rw-r--r--boost/asio/detail/winrt_async_manager.hpp2
-rw-r--r--boost/asio/detail/winrt_async_op.hpp2
-rw-r--r--boost/asio/detail/winrt_resolve_op.hpp2
-rw-r--r--boost/asio/detail/winrt_resolver_service.hpp2
-rw-r--r--boost/asio/detail/winrt_socket_connect_op.hpp2
-rw-r--r--boost/asio/detail/winrt_socket_recv_op.hpp2
-rw-r--r--boost/asio/detail/winrt_socket_send_op.hpp2
-rw-r--r--boost/asio/detail/winrt_ssocket_service.hpp3
-rw-r--r--boost/asio/detail/winrt_ssocket_service_base.hpp2
-rw-r--r--boost/asio/detail/winrt_timer_scheduler.hpp2
-rw-r--r--boost/asio/detail/winrt_utils.hpp2
-rw-r--r--boost/asio/detail/winsock_init.hpp2
-rw-r--r--boost/asio/detail/wrapped_handler.hpp2
-rw-r--r--boost/asio/error.hpp14
-rw-r--r--boost/asio/generic/basic_endpoint.hpp2
-rw-r--r--boost/asio/generic/datagram_protocol.hpp2
-rw-r--r--boost/asio/generic/detail/endpoint.hpp2
-rw-r--r--boost/asio/generic/detail/impl/endpoint.ipp2
-rw-r--r--boost/asio/generic/raw_protocol.hpp2
-rw-r--r--boost/asio/generic/seq_packet_protocol.hpp2
-rw-r--r--boost/asio/generic/stream_protocol.hpp2
-rw-r--r--boost/asio/handler_alloc_hook.hpp2
-rw-r--r--boost/asio/handler_continuation_hook.hpp2
-rw-r--r--boost/asio/handler_invoke_hook.hpp2
-rw-r--r--boost/asio/handler_type.hpp2
-rw-r--r--boost/asio/high_resolution_timer.hpp2
-rw-r--r--boost/asio/impl/buffered_read_stream.hpp2
-rw-r--r--boost/asio/impl/buffered_write_stream.hpp2
-rw-r--r--boost/asio/impl/connect.hpp2
-rw-r--r--boost/asio/impl/error.ipp2
-rw-r--r--boost/asio/impl/handler_alloc_hook.ipp2
-rw-r--r--boost/asio/impl/io_service.hpp2
-rw-r--r--boost/asio/impl/io_service.ipp2
-rw-r--r--boost/asio/impl/read.hpp2
-rw-r--r--boost/asio/impl/read_at.hpp2
-rw-r--r--boost/asio/impl/read_until.hpp2
-rw-r--r--boost/asio/impl/serial_port_base.hpp2
-rw-r--r--boost/asio/impl/serial_port_base.ipp2
-rw-r--r--boost/asio/impl/spawn.hpp2
-rw-r--r--boost/asio/impl/src.cpp2
-rw-r--r--boost/asio/impl/src.hpp2
-rw-r--r--boost/asio/impl/use_future.hpp11
-rw-r--r--boost/asio/impl/write.hpp2
-rw-r--r--boost/asio/impl/write_at.hpp2
-rw-r--r--boost/asio/io_service.hpp2
-rw-r--r--boost/asio/ip/address.hpp2
-rw-r--r--boost/asio/ip/address_v4.hpp2
-rw-r--r--boost/asio/ip/address_v6.hpp2
-rw-r--r--boost/asio/ip/basic_endpoint.hpp2
-rw-r--r--boost/asio/ip/basic_resolver.hpp2
-rw-r--r--boost/asio/ip/basic_resolver_entry.hpp2
-rw-r--r--boost/asio/ip/basic_resolver_iterator.hpp2
-rw-r--r--boost/asio/ip/basic_resolver_query.hpp2
-rw-r--r--boost/asio/ip/detail/endpoint.hpp2
-rw-r--r--boost/asio/ip/detail/impl/endpoint.ipp16
-rw-r--r--boost/asio/ip/detail/socket_option.hpp2
-rw-r--r--boost/asio/ip/host_name.hpp2
-rw-r--r--boost/asio/ip/icmp.hpp2
-rw-r--r--boost/asio/ip/impl/address.hpp2
-rw-r--r--boost/asio/ip/impl/address.ipp2
-rw-r--r--boost/asio/ip/impl/address_v4.hpp2
-rw-r--r--boost/asio/ip/impl/address_v4.ipp2
-rw-r--r--boost/asio/ip/impl/address_v6.hpp2
-rw-r--r--boost/asio/ip/impl/address_v6.ipp2
-rw-r--r--boost/asio/ip/impl/basic_endpoint.hpp2
-rw-r--r--boost/asio/ip/impl/host_name.ipp2
-rw-r--r--boost/asio/ip/multicast.hpp2
-rw-r--r--boost/asio/ip/resolver_query_base.hpp2
-rw-r--r--boost/asio/ip/resolver_service.hpp2
-rw-r--r--boost/asio/ip/tcp.hpp2
-rw-r--r--boost/asio/ip/udp.hpp2
-rw-r--r--boost/asio/ip/unicast.hpp2
-rw-r--r--boost/asio/ip/v6_only.hpp2
-rw-r--r--boost/asio/is_read_buffered.hpp2
-rw-r--r--boost/asio/is_write_buffered.hpp2
-rw-r--r--boost/asio/local/basic_endpoint.hpp2
-rw-r--r--boost/asio/local/connect_pair.hpp2
-rw-r--r--boost/asio/local/datagram_protocol.hpp2
-rw-r--r--boost/asio/local/detail/endpoint.hpp2
-rw-r--r--boost/asio/local/detail/impl/endpoint.ipp2
-rw-r--r--boost/asio/local/stream_protocol.hpp2
-rw-r--r--boost/asio/placeholders.hpp2
-rw-r--r--boost/asio/posix/basic_descriptor.hpp2
-rw-r--r--boost/asio/posix/basic_stream_descriptor.hpp2
-rw-r--r--boost/asio/posix/descriptor_base.hpp2
-rw-r--r--boost/asio/posix/stream_descriptor.hpp2
-rw-r--r--boost/asio/posix/stream_descriptor_service.hpp2
-rw-r--r--boost/asio/raw_socket_service.hpp8
-rw-r--r--boost/asio/read.hpp2
-rw-r--r--boost/asio/read_at.hpp2
-rw-r--r--boost/asio/read_until.hpp2
-rw-r--r--boost/asio/seq_packet_socket_service.hpp8
-rw-r--r--boost/asio/serial_port.hpp2
-rw-r--r--boost/asio/serial_port_base.hpp2
-rw-r--r--boost/asio/serial_port_service.hpp2
-rw-r--r--boost/asio/signal_set.hpp2
-rw-r--r--boost/asio/signal_set_service.hpp2
-rw-r--r--boost/asio/socket_acceptor_service.hpp8
-rw-r--r--boost/asio/socket_base.hpp2
-rw-r--r--boost/asio/spawn.hpp2
-rw-r--r--boost/asio/ssl.hpp2
-rw-r--r--boost/asio/ssl/basic_context.hpp2
-rw-r--r--boost/asio/ssl/context.hpp2
-rw-r--r--boost/asio/ssl/context_base.hpp13
-rw-r--r--boost/asio/ssl/context_service.hpp2
-rw-r--r--boost/asio/ssl/detail/buffered_handshake_op.hpp2
-rw-r--r--boost/asio/ssl/detail/engine.hpp2
-rw-r--r--boost/asio/ssl/detail/handshake_op.hpp2
-rw-r--r--boost/asio/ssl/detail/impl/engine.ipp2
-rw-r--r--boost/asio/ssl/detail/impl/openssl_init.ipp9
-rw-r--r--boost/asio/ssl/detail/io.hpp2
-rw-r--r--boost/asio/ssl/detail/openssl_init.hpp2
-rw-r--r--boost/asio/ssl/detail/openssl_types.hpp4
-rw-r--r--boost/asio/ssl/detail/password_callback.hpp2
-rw-r--r--boost/asio/ssl/detail/read_op.hpp2
-rw-r--r--boost/asio/ssl/detail/shutdown_op.hpp2
-rw-r--r--boost/asio/ssl/detail/stream_core.hpp2
-rw-r--r--boost/asio/ssl/detail/verify_callback.hpp2
-rw-r--r--boost/asio/ssl/detail/write_op.hpp2
-rw-r--r--boost/asio/ssl/error.hpp9
-rw-r--r--boost/asio/ssl/impl/context.hpp2
-rw-r--r--boost/asio/ssl/impl/context.ipp202
-rw-r--r--boost/asio/ssl/impl/error.ipp2
-rw-r--r--boost/asio/ssl/impl/rfc2818_verification.ipp2
-rw-r--r--boost/asio/ssl/impl/src.hpp2
-rw-r--r--boost/asio/ssl/old/basic_context.hpp2
-rw-r--r--boost/asio/ssl/old/context_service.hpp2
-rw-r--r--boost/asio/ssl/old/detail/openssl_context_service.hpp2
-rw-r--r--boost/asio/ssl/old/detail/openssl_stream_service.hpp2
-rw-r--r--boost/asio/ssl/old/stream.hpp2
-rw-r--r--boost/asio/ssl/old/stream_service.hpp2
-rw-r--r--boost/asio/ssl/rfc2818_verification.hpp2
-rw-r--r--boost/asio/ssl/stream.hpp2
-rw-r--r--boost/asio/ssl/stream_base.hpp2
-rw-r--r--boost/asio/ssl/stream_service.hpp2
-rw-r--r--boost/asio/ssl/verify_context.hpp2
-rw-r--r--boost/asio/ssl/verify_mode.hpp2
-rw-r--r--boost/asio/steady_timer.hpp2
-rw-r--r--boost/asio/strand.hpp2
-rw-r--r--boost/asio/stream_socket_service.hpp8
-rw-r--r--boost/asio/streambuf.hpp2
-rw-r--r--boost/asio/system_timer.hpp2
-rw-r--r--boost/asio/time_traits.hpp2
-rw-r--r--boost/asio/unyield.hpp2
-rw-r--r--boost/asio/use_future.hpp2
-rw-r--r--boost/asio/version.hpp4
-rw-r--r--boost/asio/wait_traits.hpp2
-rw-r--r--boost/asio/waitable_timer_service.hpp2
-rw-r--r--boost/asio/windows/basic_handle.hpp2
-rw-r--r--boost/asio/windows/basic_object_handle.hpp2
-rw-r--r--boost/asio/windows/basic_random_access_handle.hpp2
-rw-r--r--boost/asio/windows/basic_stream_handle.hpp2
-rw-r--r--boost/asio/windows/object_handle.hpp2
-rw-r--r--boost/asio/windows/object_handle_service.hpp2
-rw-r--r--boost/asio/windows/overlapped_ptr.hpp2
-rw-r--r--boost/asio/windows/random_access_handle.hpp2
-rw-r--r--boost/asio/windows/random_access_handle_service.hpp2
-rw-r--r--boost/asio/windows/stream_handle.hpp2
-rw-r--r--boost/asio/windows/stream_handle_service.hpp2
-rw-r--r--boost/asio/write.hpp2
-rw-r--r--boost/asio/write_at.hpp2
-rw-r--r--boost/asio/yield.hpp2
-rw-r--r--boost/atomic/detail/bitwise_cast.hpp15
-rw-r--r--boost/atomic/detail/interlocked.hpp9
-rw-r--r--boost/atomic/detail/ops_gcc_x86_dcas.hpp14
-rw-r--r--boost/atomic/detail/platform.hpp2
-rw-r--r--boost/cerrno.hpp4
-rw-r--r--boost/config/auto_link.hpp11
-rw-r--r--boost/config/compiler/borland.hpp1
-rw-r--r--boost/config/compiler/clang.hpp6
-rw-r--r--boost/config/compiler/codegear.hpp1
-rw-r--r--boost/config/compiler/common_edg.hpp1
-rw-r--r--boost/config/compiler/cray.hpp1
-rw-r--r--boost/config/compiler/digitalmars.hpp1
-rw-r--r--boost/config/compiler/gcc.hpp1
-rw-r--r--boost/config/compiler/gcc_xml.hpp1
-rw-r--r--boost/config/compiler/hp_acc.hpp1
-rw-r--r--boost/config/compiler/intel.hpp25
-rw-r--r--boost/config/compiler/metrowerks.hpp1
-rw-r--r--boost/config/compiler/mpw.hpp1
-rw-r--r--boost/config/compiler/pathscale.hpp1
-rw-r--r--boost/config/compiler/pgi.hpp1
-rw-r--r--boost/config/compiler/sunpro_cc.hpp1
-rw-r--r--boost/config/compiler/vacpp.hpp1
-rw-r--r--boost/config/compiler/visualc.hpp29
-rw-r--r--boost/config/platform/cygwin.hpp3
-rw-r--r--boost/config/stdlib/dinkumware.hpp30
-rw-r--r--boost/config/stdlib/libstdcpp3.hpp8
-rw-r--r--boost/config/suffix.hpp21
-rw-r--r--boost/container/allocator_traits.hpp54
-rw-r--r--boost/container/detail/advanced_insert_int.hpp4
-rw-r--r--boost/container/detail/dispatch_uses_allocator.hpp56
-rw-r--r--boost/container/detail/hash_table.hpp383
-rw-r--r--boost/container/detail/mutex.hpp13
-rw-r--r--boost/container/detail/workaround.hpp4
-rw-r--r--boost/container/new_allocator.hpp6
-rw-r--r--boost/container/node_handle.hpp5
-rw-r--r--boost/container/small_vector.hpp2
-rw-r--r--boost/container/string.hpp473
-rw-r--r--boost/container/vector.hpp10
-rw-r--r--boost/context/all.hpp4
-rw-r--r--boost/context/continuation.hpp554
-rw-r--r--boost/context/execution_context_v1.hpp6
-rw-r--r--boost/context/execution_context_v2.hpp4
-rw-r--r--boost/context/execution_context_v2_void.ipp2
-rw-r--r--boost/context/fixedsize_stack.hpp79
-rw-r--r--boost/context/posix/fixedsize_stack.hpp80
-rw-r--r--boost/context/posix/protected_fixedsize_stack.hpp4
-rw-r--r--boost/context/posix/segmented_stack.hpp2
-rw-r--r--boost/context/windows/fixedsize_stack.hpp80
-rw-r--r--boost/context/windows/protected_fixedsize_stack.hpp4
-rw-r--r--boost/convert/base.hpp68
-rw-r--r--boost/convert/detail/forward.hpp13
-rw-r--r--boost/core/addressof.hpp301
-rw-r--r--boost/core/demangle.hpp13
-rw-r--r--boost/core/lightweight_test.hpp191
-rw-r--r--boost/coroutine2/detail/config.hpp3
-rw-r--r--boost/coroutine2/detail/coroutine.hpp8
-rw-r--r--boost/coroutine2/detail/forced_unwind.hpp2
-rw-r--r--boost/coroutine2/detail/pull_control_block_cc.hpp (renamed from boost/coroutine2/detail/pull_control_block_ecv2.hpp)40
-rw-r--r--boost/coroutine2/detail/pull_control_block_cc.ipp452
-rw-r--r--boost/coroutine2/detail/pull_control_block_ecv1.ipp22
-rw-r--r--boost/coroutine2/detail/pull_control_block_ecv2.ipp422
-rw-r--r--boost/coroutine2/detail/pull_coroutine.hpp4
-rw-r--r--boost/coroutine2/detail/push_control_block_cc.hpp (renamed from boost/coroutine2/detail/push_control_block_ecv2.hpp)14
-rw-r--r--boost/coroutine2/detail/push_control_block_cc.ipp400
-rw-r--r--boost/coroutine2/detail/push_control_block_ecv1.ipp22
-rw-r--r--boost/coroutine2/detail/push_control_block_ecv2.ipp392
-rw-r--r--boost/coroutine2/detail/push_coroutine.hpp8
-rw-r--r--boost/coroutine2/detail/wrap.hpp112
-rw-r--r--boost/date_time/c_time.hpp26
-rw-r--r--boost/date_time/constrained_value.hpp6
-rw-r--r--boost/date_time/date.hpp3
-rw-r--r--boost/date_time/date_duration.hpp7
-rw-r--r--boost/date_time/date_duration_types.hpp11
-rw-r--r--boost/date_time/date_facet.hpp4
-rw-r--r--boost/date_time/date_names_put.hpp15
-rw-r--r--boost/date_time/gregorian/greg_calendar.hpp3
-rw-r--r--boost/date_time/gregorian/greg_date.hpp3
-rw-r--r--boost/date_time/gregorian/greg_day.hpp7
-rw-r--r--boost/date_time/gregorian/greg_day_of_year.hpp5
-rw-r--r--boost/date_time/gregorian/greg_duration.hpp3
-rw-r--r--boost/date_time/gregorian/greg_duration_types.hpp7
-rw-r--r--boost/date_time/gregorian/greg_facet.hpp14
-rw-r--r--boost/date_time/gregorian/greg_month.hpp10
-rw-r--r--boost/date_time/gregorian/greg_weekday.hpp8
-rw-r--r--boost/date_time/gregorian/greg_year.hpp9
-rw-r--r--boost/date_time/gregorian_calendar.hpp3
-rw-r--r--boost/date_time/local_time/local_date_time.hpp9
-rw-r--r--boost/date_time/local_time/posix_time_zone.hpp7
-rw-r--r--boost/date_time/period.hpp5
-rw-r--r--boost/date_time/posix_time/date_duration_operators.hpp2
-rw-r--r--boost/date_time/posix_time/posix_time_config.hpp4
-rw-r--r--boost/date_time/posix_time/posix_time_duration.hpp9
-rw-r--r--boost/date_time/posix_time/ptime.hpp11
-rw-r--r--boost/date_time/time_duration.hpp4
-rw-r--r--boost/date_time/time_facet.hpp4
-rw-r--r--boost/date_time/time_zone_base.hpp3
-rw-r--r--boost/date_time/year_month_day.hpp4
-rw-r--r--boost/detail/lcast_precision.hpp1
-rw-r--r--boost/detail/winapi/config.hpp8
-rw-r--r--boost/detail/winapi/crypt.hpp43
-rw-r--r--boost/detail/winapi/jobs.hpp4
-rw-r--r--boost/detail/workaround.hpp5
-rw-r--r--boost/dll/detail/aggressive_ptr_cast.hpp31
-rw-r--r--boost/dll/detail/demangling/msvc.hpp2
-rw-r--r--boost/dll/detail/import_mangled_helpers.hpp60
-rw-r--r--boost/dll/detail/posix/path_from_handle.hpp4
-rw-r--r--boost/dll/import_mangled.hpp29
-rw-r--r--boost/dll/runtime_symbol_info.hpp77
-rw-r--r--boost/dll/smart_library.hpp2
-rw-r--r--boost/dynamic_bitset/dynamic_bitset.hpp4
-rw-r--r--boost/dynamic_bitset/serialization.hpp46
-rw-r--r--boost/fiber/algo/algorithm.hpp34
-rw-r--r--boost/fiber/algo/detail/chase_lev_queue.hpp172
-rw-r--r--boost/fiber/algo/round_robin.hpp4
-rw-r--r--boost/fiber/algo/shared_work.hpp12
-rw-r--r--boost/fiber/algo/work_stealing.hpp42
-rw-r--r--boost/fiber/barrier.hpp14
-rw-r--r--boost/fiber/bounded_channel.hpp433
-rw-r--r--boost/fiber/buffered_channel.hpp510
-rw-r--r--boost/fiber/condition_variable.hpp47
-rw-r--r--boost/fiber/context.hpp267
-rw-r--r--boost/fiber/detail/config.hpp2
-rw-r--r--boost/fiber/detail/context_mpsc_queue.hpp98
-rw-r--r--boost/fiber/detail/context_spinlock_queue.hpp118
-rw-r--r--boost/fiber/detail/context_spmc_queue.hpp99
-rw-r--r--boost/fiber/detail/cpu_relax.hpp36
-rw-r--r--boost/fiber/detail/data.hpp2
-rw-r--r--boost/fiber/detail/fss.hpp5
-rw-r--r--boost/fiber/detail/futex.hpp2
-rw-r--r--boost/fiber/detail/spinlock_ttas.hpp29
-rw-r--r--boost/fiber/detail/spinlock_ttas_adaptive.hpp21
-rw-r--r--boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp14
-rw-r--r--boost/fiber/detail/spinlock_ttas_futex.hpp12
-rw-r--r--boost/fiber/detail/wrap.hpp51
-rw-r--r--boost/fiber/exceptions.hpp30
-rw-r--r--boost/fiber/fiber.hpp8
-rw-r--r--boost/fiber/fss.hpp6
-rw-r--r--boost/fiber/future/async.hpp78
-rw-r--r--boost/fiber/future/detail/shared_state.hpp47
-rw-r--r--boost/fiber/future/detail/shared_state_object.hpp13
-rw-r--r--boost/fiber/future/detail/task_base.hpp4
-rw-r--r--boost/fiber/future/detail/task_object.hpp88
-rw-r--r--boost/fiber/future/future.hpp233
-rw-r--r--boost/fiber/future/packaged_task.hpp27
-rw-r--r--boost/fiber/future/promise.hpp69
-rw-r--r--boost/fiber/mutex.hpp6
-rw-r--r--boost/fiber/operations.hpp8
-rw-r--r--boost/fiber/recursive_mutex.hpp6
-rw-r--r--boost/fiber/recursive_timed_mutex.hpp9
-rw-r--r--boost/fiber/scheduler.hpp71
-rw-r--r--boost/fiber/timed_mutex.hpp9
-rw-r--r--boost/fiber/type.hpp1
-rw-r--r--boost/fiber/unbounded_channel.hpp272
-rw-r--r--boost/fiber/unbuffered_channel.hpp199
-rw-r--r--boost/filesystem/detail/macro_value.hpp44
-rw-r--r--boost/function/function_template.hpp11
-rw-r--r--boost/functional.hpp61
-rw-r--r--boost/functional/hash/extensions.hpp6
-rw-r--r--boost/functional/hash/hash.hpp20
-rw-r--r--boost/geometry/algorithms/area.hpp7
-rw-r--r--boost/geometry/algorithms/buffer.hpp10
-rw-r--r--boost/geometry/algorithms/centroid.hpp7
-rw-r--r--boost/geometry/algorithms/covered_by.hpp31
-rw-r--r--boost/geometry/algorithms/crosses.hpp141
-rw-r--r--boost/geometry/algorithms/detail/azimuth.hpp25
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp57
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_policies.hpp6
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp49
-rw-r--r--boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp12
-rw-r--r--boost/geometry/algorithms/detail/calculate_sum.hpp6
-rw-r--r--boost/geometry/algorithms/detail/disjoint/areal_areal.hpp74
-rw-r--r--boost/geometry/algorithms/detail/disjoint/box_box.hpp16
-rw-r--r--boost/geometry/algorithms/detail/disjoint/interface.hpp157
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_areal.hpp87
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_linear.hpp38
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp11
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp88
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp25
-rw-r--r--boost/geometry/algorithms/detail/disjoint/point_box.hpp28
-rw-r--r--boost/geometry/algorithms/detail/disjoint/point_geometry.hpp9
-rw-r--r--boost/geometry/algorithms/detail/disjoint/point_point.hpp18
-rw-r--r--boost/geometry/algorithms/detail/disjoint/segment_box.hpp242
-rw-r--r--boost/geometry/algorithms/detail/envelope/box.hpp17
-rw-r--r--boost/geometry/algorithms/detail/envelope/implementation.hpp13
-rw-r--r--boost/geometry/algorithms/detail/envelope/interface.hpp124
-rw-r--r--boost/geometry/algorithms/detail/envelope/linear.hpp28
-rw-r--r--boost/geometry/algorithms/detail/envelope/multipoint.hpp13
-rw-r--r--boost/geometry/algorithms/detail/envelope/point.hpp15
-rw-r--r--boost/geometry/algorithms/detail/envelope/range.hpp44
-rw-r--r--boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp21
-rw-r--r--boost/geometry/algorithms/detail/envelope/segment.hpp209
-rw-r--r--boost/geometry/algorithms/detail/equals/collect_vectors.hpp97
-rw-r--r--boost/geometry/algorithms/detail/expand/box.hpp17
-rw-r--r--boost/geometry/algorithms/detail/expand/indexed.hpp25
-rw-r--r--boost/geometry/algorithms/detail/expand/interface.hpp99
-rw-r--r--boost/geometry/algorithms/detail/expand/point.hpp27
-rw-r--r--boost/geometry/algorithms/detail/expand/segment.hpp42
-rw-r--r--boost/geometry/algorithms/detail/has_self_intersections.hpp23
-rw-r--r--boost/geometry/algorithms/detail/intersection/interface.hpp279
-rw-r--r--boost/geometry/algorithms/detail/is_simple/always_simple.hpp6
-rw-r--r--boost/geometry/algorithms/detail/is_simple/areal.hpp18
-rw-r--r--boost/geometry/algorithms/detail/is_simple/interface.hpp77
-rw-r--r--boost/geometry/algorithms/detail/is_simple/linear.hpp31
-rw-r--r--boost/geometry/algorithms/detail/is_simple/multipoint.hpp6
-rw-r--r--boost/geometry/algorithms/detail/is_valid/box.hpp6
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp15
-rw-r--r--boost/geometry/algorithms/detail/is_valid/interface.hpp163
-rw-r--r--boost/geometry/algorithms/detail/is_valid/linear.hpp15
-rw-r--r--boost/geometry/algorithms/detail/is_valid/multipolygon.hpp33
-rw-r--r--boost/geometry/algorithms/detail/is_valid/pointlike.hpp11
-rw-r--r--boost/geometry/algorithms/detail/is_valid/polygon.hpp49
-rw-r--r--boost/geometry/algorithms/detail/is_valid/ring.hpp47
-rw-r--r--boost/geometry/algorithms/detail/is_valid/segment.hpp6
-rw-r--r--boost/geometry/algorithms/detail/not.hpp13
-rw-r--r--boost/geometry/algorithms/detail/overlay/assign_parents.hpp9
-rw-r--r--boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp40
-rw-r--r--boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp5
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp49
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info.hpp31
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp21
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp139
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp59
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp32
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turns.hpp130
-rw-r--r--boost/geometry/algorithms/detail/overlay/intersection_insert.hpp63
-rw-r--r--boost/geometry/algorithms/detail/overlay/linear_linear.hpp11
-rw-r--r--boost/geometry/algorithms/detail/overlay/overlay.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp42
-rw-r--r--boost/geometry/algorithms/detail/overlay/self_turn_points.hpp42
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp11
-rw-r--r--boost/geometry/algorithms/detail/overlay/traverse.hpp5
-rw-r--r--boost/geometry/algorithms/detail/partition.hpp499
-rw-r--r--boost/geometry/algorithms/detail/relate/areal_areal.hpp87
-rw-r--r--boost/geometry/algorithms/detail/relate/implementation.hpp7
-rw-r--r--boost/geometry/algorithms/detail/relate/interface.hpp135
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_areal.hpp79
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_linear.hpp16
-rw-r--r--boost/geometry/algorithms/detail/relate/point_geometry.hpp16
-rw-r--r--boost/geometry/algorithms/detail/relate/point_point.hpp34
-rw-r--r--boost/geometry/algorithms/detail/relate/relate_impl.hpp5
-rw-r--r--boost/geometry/algorithms/detail/relate/result.hpp4
-rw-r--r--boost/geometry/algorithms/detail/relate/turns.hpp24
-rw-r--r--boost/geometry/algorithms/detail/relation/interface.hpp93
-rw-r--r--boost/geometry/algorithms/detail/throw_on_empty_input.hpp7
-rw-r--r--boost/geometry/algorithms/detail/within/point_in_geometry.hpp98
-rw-r--r--boost/geometry/algorithms/difference.hpp305
-rw-r--r--boost/geometry/algorithms/dispatch/disjoint.hpp27
-rw-r--r--boost/geometry/algorithms/equals.hpp319
-rw-r--r--boost/geometry/algorithms/intersects.hpp40
-rw-r--r--boost/geometry/algorithms/overlaps.hpp46
-rw-r--r--boost/geometry/algorithms/sym_difference.hpp288
-rw-r--r--boost/geometry/algorithms/touches.hpp212
-rw-r--r--boost/geometry/algorithms/union.hpp294
-rw-r--r--boost/geometry/algorithms/within.hpp37
-rw-r--r--boost/geometry/arithmetic/normalize.hpp71
-rw-r--r--boost/geometry/core/srs.hpp9
-rw-r--r--boost/geometry/formulas/andoyer_inverse.hpp27
-rw-r--r--boost/geometry/formulas/area_formulas.hpp578
-rw-r--r--boost/geometry/formulas/differential_quantities.hpp19
-rw-r--r--boost/geometry/formulas/eccentricity_sqr.hpp70
-rw-r--r--boost/geometry/formulas/flattening.hpp (renamed from boost/geometry/algorithms/detail/flattening.hpp)19
-rw-r--r--boost/geometry/formulas/geographic.hpp457
-rw-r--r--boost/geometry/formulas/gnomonic_spheroid.hpp3
-rw-r--r--boost/geometry/formulas/sjoberg_intersection.hpp1310
-rw-r--r--boost/geometry/formulas/spherical.hpp152
-rw-r--r--boost/geometry/formulas/thomas_direct.hpp5
-rw-r--r--boost/geometry/formulas/thomas_inverse.hpp5
-rw-r--r--boost/geometry/formulas/vertex_latitude.hpp148
-rw-r--r--boost/geometry/formulas/vincenty_direct.hpp5
-rw-r--r--boost/geometry/formulas/vincenty_inverse.hpp38
-rw-r--r--boost/geometry/index/detail/algorithms/nth_element.hpp62
-rw-r--r--boost/geometry/index/detail/rtree/pack_create.hpp5
-rw-r--r--boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp5
-rw-r--r--boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp12
-rw-r--r--boost/geometry/index/equal_to.hpp11
-rw-r--r--boost/geometry/index/parameters.hpp24
-rw-r--r--boost/geometry/io/wkt/read.hpp26
-rw-r--r--boost/geometry/policies/robustness/segment_ratio.hpp20
-rw-r--r--boost/geometry/strategies/agnostic/point_in_point.hpp77
-rw-r--r--boost/geometry/strategies/agnostic/point_in_poly_winding.hpp69
-rw-r--r--boost/geometry/strategies/agnostic/relate.hpp122
-rw-r--r--boost/geometry/strategies/azimuth.hpp44
-rw-r--r--boost/geometry/strategies/cartesian/area_surveyor.hpp5
-rw-r--r--boost/geometry/strategies/cartesian/azimuth.hpp49
-rw-r--r--boost/geometry/strategies/cartesian/box_in_box.hpp28
-rw-r--r--boost/geometry/strategies/cartesian/disjoint_segment_box.hpp320
-rw-r--r--boost/geometry/strategies/cartesian/envelope_segment.hpp71
-rw-r--r--boost/geometry/strategies/cartesian/intersection.hpp (renamed from boost/geometry/strategies/cartesian/cart_intersect.hpp)262
-rw-r--r--boost/geometry/strategies/cartesian/point_in_box.hpp28
-rw-r--r--boost/geometry/strategies/covered_by.hpp51
-rw-r--r--boost/geometry/strategies/disjoint.hpp90
-rw-r--r--boost/geometry/strategies/envelope.hpp45
-rw-r--r--boost/geometry/strategies/geographic/area.hpp216
-rw-r--r--boost/geometry/strategies/geographic/azimuth.hpp103
-rw-r--r--boost/geometry/strategies/geographic/distance.hpp195
-rw-r--r--boost/geometry/strategies/geographic/distance_andoyer.hpp90
-rw-r--r--boost/geometry/strategies/geographic/distance_thomas.hpp67
-rw-r--r--boost/geometry/strategies/geographic/distance_vincenty.hpp67
-rw-r--r--boost/geometry/strategies/geographic/envelope_segment.hpp104
-rw-r--r--boost/geometry/strategies/geographic/intersection.hpp897
-rw-r--r--boost/geometry/strategies/geographic/intersection_elliptic.hpp243
-rw-r--r--boost/geometry/strategies/geographic/mapping_ssf.hpp6
-rw-r--r--boost/geometry/strategies/geographic/parameters.hpp117
-rw-r--r--boost/geometry/strategies/geographic/side.hpp113
-rw-r--r--boost/geometry/strategies/geographic/side_andoyer.hpp25
-rw-r--r--boost/geometry/strategies/geographic/side_detail.hpp139
-rw-r--r--boost/geometry/strategies/geographic/side_thomas.hpp25
-rw-r--r--boost/geometry/strategies/geographic/side_vincenty.hpp25
-rw-r--r--boost/geometry/strategies/intersection.hpp5
-rw-r--r--boost/geometry/strategies/intersection_strategies.hpp25
-rw-r--r--boost/geometry/strategies/relate.hpp177
-rw-r--r--boost/geometry/strategies/side.hpp6
-rw-r--r--boost/geometry/strategies/spherical/area.hpp182
-rw-r--r--boost/geometry/strategies/spherical/area_huiller.hpp214
-rw-r--r--boost/geometry/strategies/spherical/azimuth.hpp87
-rw-r--r--boost/geometry/strategies/spherical/envelope_segment.hpp86
-rw-r--r--boost/geometry/strategies/spherical/intersection.hpp525
-rw-r--r--boost/geometry/strategies/strategies.hpp33
-rw-r--r--boost/geometry/strategies/transform/inverse_transformer.hpp33
-rw-r--r--boost/geometry/strategies/transform/map_transformer.hpp53
-rw-r--r--boost/geometry/strategies/transform/matrix_transformers.hpp98
-rw-r--r--boost/geometry/strategies/within.hpp51
-rw-r--r--boost/geometry/util/math.hpp15
-rw-r--r--boost/geometry/util/normalize_spheroidal_coordinates.hpp34
-rw-r--r--boost/hana.hpp2
-rw-r--r--boost/hana/accessors.hpp2
-rw-r--r--boost/hana/adapt_adt.hpp2
-rw-r--r--boost/hana/adapt_struct.hpp2
-rw-r--r--boost/hana/adjust.hpp2
-rw-r--r--boost/hana/adjust_if.hpp2
-rw-r--r--boost/hana/all.hpp2
-rw-r--r--boost/hana/all_of.hpp2
-rw-r--r--boost/hana/and.hpp2
-rw-r--r--boost/hana/any.hpp2
-rw-r--r--boost/hana/any_of.hpp30
-rw-r--r--boost/hana/ap.hpp2
-rw-r--r--boost/hana/append.hpp2
-rw-r--r--boost/hana/assert.hpp2
-rw-r--r--boost/hana/at.hpp2
-rw-r--r--boost/hana/at_key.hpp2
-rw-r--r--boost/hana/back.hpp2
-rw-r--r--boost/hana/basic_tuple.hpp129
-rw-r--r--boost/hana/bool.hpp2
-rw-r--r--boost/hana/cartesian_product.hpp2
-rw-r--r--boost/hana/chain.hpp2
-rw-r--r--boost/hana/comparing.hpp2
-rw-r--r--boost/hana/concat.hpp2
-rw-r--r--boost/hana/concept.hpp2
-rw-r--r--boost/hana/concept/applicative.hpp2
-rw-r--r--boost/hana/concept/comonad.hpp2
-rw-r--r--boost/hana/concept/comparable.hpp2
-rw-r--r--boost/hana/concept/constant.hpp2
-rw-r--r--boost/hana/concept/euclidean_ring.hpp2
-rw-r--r--boost/hana/concept/foldable.hpp2
-rw-r--r--boost/hana/concept/functor.hpp2
-rw-r--r--boost/hana/concept/group.hpp2
-rw-r--r--boost/hana/concept/integral_constant.hpp2
-rw-r--r--boost/hana/concept/iterable.hpp2
-rw-r--r--boost/hana/concept/logical.hpp2
-rw-r--r--boost/hana/concept/metafunction.hpp2
-rw-r--r--boost/hana/concept/monad.hpp2
-rw-r--r--boost/hana/concept/monad_plus.hpp2
-rw-r--r--boost/hana/concept/monoid.hpp2
-rw-r--r--boost/hana/concept/orderable.hpp2
-rw-r--r--boost/hana/concept/product.hpp2
-rw-r--r--boost/hana/concept/ring.hpp2
-rw-r--r--boost/hana/concept/searchable.hpp2
-rw-r--r--boost/hana/concept/sequence.hpp2
-rw-r--r--boost/hana/concept/struct.hpp2
-rw-r--r--boost/hana/config.hpp2
-rw-r--r--boost/hana/contains.hpp2
-rw-r--r--boost/hana/core.hpp2
-rw-r--r--boost/hana/core/common.hpp2
-rw-r--r--boost/hana/core/default.hpp2
-rw-r--r--boost/hana/core/dispatch.hpp2
-rw-r--r--boost/hana/core/is_a.hpp2
-rw-r--r--boost/hana/core/make.hpp2
-rw-r--r--boost/hana/core/tag_of.hpp2
-rw-r--r--boost/hana/core/to.hpp2
-rw-r--r--boost/hana/core/when.hpp2
-rw-r--r--boost/hana/count.hpp2
-rw-r--r--boost/hana/count_if.hpp2
-rw-r--r--boost/hana/cycle.hpp2
-rw-r--r--boost/hana/define_struct.hpp2
-rw-r--r--boost/hana/detail/algorithm.hpp2
-rw-r--r--boost/hana/detail/any_of.hpp2
-rw-r--r--boost/hana/detail/array.hpp2
-rw-r--r--boost/hana/detail/canonical_constant.hpp2
-rw-r--r--boost/hana/detail/concepts.hpp2
-rw-r--r--boost/hana/detail/create.hpp2
-rw-r--r--boost/hana/detail/decay.hpp2
-rw-r--r--boost/hana/detail/dependent_on.hpp24
-rw-r--r--boost/hana/detail/dispatch_if.hpp2
-rw-r--r--boost/hana/detail/ebo.hpp115
-rw-r--r--boost/hana/detail/fast_and.hpp2
-rw-r--r--boost/hana/detail/first_unsatisfied_index.hpp2
-rw-r--r--boost/hana/detail/has_common_embedding.hpp2
-rw-r--r--boost/hana/detail/has_duplicates.hpp2
-rw-r--r--boost/hana/detail/index_if.hpp2
-rw-r--r--boost/hana/detail/integral_constant.hpp2
-rw-r--r--boost/hana/detail/intrinsics.hpp2
-rw-r--r--boost/hana/detail/nested_by.hpp2
-rw-r--r--boost/hana/detail/nested_by_fwd.hpp2
-rw-r--r--boost/hana/detail/nested_than.hpp2
-rw-r--r--boost/hana/detail/nested_than_fwd.hpp2
-rw-r--r--boost/hana/detail/nested_to.hpp2
-rw-r--r--boost/hana/detail/nested_to_fwd.hpp2
-rw-r--r--boost/hana/detail/operators/adl.hpp2
-rw-r--r--boost/hana/detail/operators/arithmetic.hpp2
-rw-r--r--boost/hana/detail/operators/comparable.hpp2
-rw-r--r--boost/hana/detail/operators/iterable.hpp2
-rw-r--r--boost/hana/detail/operators/logical.hpp2
-rw-r--r--boost/hana/detail/operators/monad.hpp2
-rw-r--r--boost/hana/detail/operators/orderable.hpp2
-rw-r--r--boost/hana/detail/operators/searchable.hpp2
-rw-r--r--boost/hana/detail/preprocessor.hpp2
-rw-r--r--boost/hana/detail/std_common_type.hpp2
-rw-r--r--boost/hana/detail/struct_macros.erb.hpp2
-rw-r--r--boost/hana/detail/struct_macros.hpp2
-rw-r--r--boost/hana/detail/type_at.hpp2
-rw-r--r--boost/hana/detail/type_foldl1.hpp2
-rw-r--r--boost/hana/detail/type_foldr1.hpp2
-rw-r--r--boost/hana/detail/unpack_flatten.hpp2
-rw-r--r--boost/hana/detail/variadic/at.hpp2
-rw-r--r--boost/hana/detail/variadic/drop_into.hpp2
-rw-r--r--boost/hana/detail/variadic/foldl1.hpp2
-rw-r--r--boost/hana/detail/variadic/foldr1.hpp2
-rw-r--r--boost/hana/detail/variadic/reverse_apply.hpp2
-rw-r--r--boost/hana/detail/variadic/reverse_apply/flat.hpp2
-rw-r--r--boost/hana/detail/variadic/reverse_apply/unrolled.hpp2
-rw-r--r--boost/hana/detail/variadic/split_at.hpp2
-rw-r--r--boost/hana/detail/variadic/take.hpp2
-rw-r--r--boost/hana/detail/void_t.hpp2
-rw-r--r--boost/hana/detail/wrong.hpp2
-rw-r--r--boost/hana/difference.hpp2
-rw-r--r--boost/hana/div.hpp2
-rw-r--r--boost/hana/drop_back.hpp2
-rw-r--r--boost/hana/drop_front.hpp2
-rw-r--r--boost/hana/drop_front_exactly.hpp2
-rw-r--r--boost/hana/drop_while.hpp2
-rw-r--r--boost/hana/duplicate.hpp2
-rw-r--r--boost/hana/empty.hpp2
-rw-r--r--boost/hana/equal.hpp6
-rw-r--r--boost/hana/erase_key.hpp2
-rw-r--r--boost/hana/eval.hpp2
-rw-r--r--boost/hana/eval_if.hpp8
-rw-r--r--boost/hana/experimental/printable.hpp2
-rw-r--r--boost/hana/experimental/type_name.hpp2
-rw-r--r--boost/hana/experimental/types.hpp2
-rw-r--r--boost/hana/experimental/view.hpp2
-rw-r--r--boost/hana/ext/boost.hpp2
-rw-r--r--boost/hana/ext/boost/fusion.hpp2
-rw-r--r--boost/hana/ext/boost/fusion/deque.hpp2
-rw-r--r--boost/hana/ext/boost/fusion/detail/common.hpp2
-rw-r--r--boost/hana/ext/boost/fusion/list.hpp2
-rw-r--r--boost/hana/ext/boost/fusion/tuple.hpp2
-rw-r--r--boost/hana/ext/boost/fusion/vector.hpp2
-rw-r--r--boost/hana/ext/boost/mpl.hpp2
-rw-r--r--boost/hana/ext/boost/mpl/integral_c.hpp2
-rw-r--r--boost/hana/ext/boost/mpl/list.hpp2
-rw-r--r--boost/hana/ext/boost/mpl/vector.hpp2
-rw-r--r--boost/hana/ext/boost/tuple.hpp2
-rw-r--r--boost/hana/ext/std.hpp2
-rw-r--r--boost/hana/ext/std/array.hpp2
-rw-r--r--boost/hana/ext/std/integer_sequence.hpp6
-rw-r--r--boost/hana/ext/std/integral_constant.hpp2
-rw-r--r--boost/hana/ext/std/pair.hpp2
-rw-r--r--boost/hana/ext/std/ratio.hpp2
-rw-r--r--boost/hana/ext/std/tuple.hpp2
-rw-r--r--boost/hana/ext/std/vector.hpp2
-rw-r--r--boost/hana/extend.hpp2
-rw-r--r--boost/hana/extract.hpp2
-rw-r--r--boost/hana/fill.hpp2
-rw-r--r--boost/hana/filter.hpp8
-rw-r--r--boost/hana/find.hpp2
-rw-r--r--boost/hana/find_if.hpp2
-rw-r--r--boost/hana/first.hpp2
-rw-r--r--boost/hana/flatten.hpp2
-rw-r--r--boost/hana/fold.hpp2
-rw-r--r--boost/hana/fold_left.hpp2
-rw-r--r--boost/hana/fold_right.hpp2
-rw-r--r--boost/hana/for_each.hpp2
-rw-r--r--boost/hana/front.hpp2
-rw-r--r--boost/hana/functional.hpp2
-rw-r--r--boost/hana/functional/always.hpp2
-rw-r--r--boost/hana/functional/apply.hpp2
-rw-r--r--boost/hana/functional/arg.hpp2
-rw-r--r--boost/hana/functional/capture.hpp4
-rw-r--r--boost/hana/functional/compose.hpp2
-rw-r--r--boost/hana/functional/curry.hpp2
-rw-r--r--boost/hana/functional/demux.hpp26
-rw-r--r--boost/hana/functional/fix.hpp2
-rw-r--r--boost/hana/functional/flip.hpp2
-rw-r--r--boost/hana/functional/id.hpp2
-rw-r--r--boost/hana/functional/infix.hpp2
-rw-r--r--boost/hana/functional/iterate.hpp2
-rw-r--r--boost/hana/functional/lockstep.hpp14
-rw-r--r--boost/hana/functional/on.hpp2
-rw-r--r--boost/hana/functional/overload.hpp2
-rw-r--r--boost/hana/functional/overload_linearly.hpp2
-rw-r--r--boost/hana/functional/partial.hpp14
-rw-r--r--boost/hana/functional/placeholder.hpp4
-rw-r--r--boost/hana/functional/reverse_partial.hpp14
-rw-r--r--boost/hana/fuse.hpp2
-rw-r--r--boost/hana/fwd/accessors.hpp2
-rw-r--r--boost/hana/fwd/adapt_adt.hpp2
-rw-r--r--boost/hana/fwd/adapt_struct.hpp2
-rw-r--r--boost/hana/fwd/adjust.hpp2
-rw-r--r--boost/hana/fwd/adjust_if.hpp2
-rw-r--r--boost/hana/fwd/all.hpp2
-rw-r--r--boost/hana/fwd/all_of.hpp2
-rw-r--r--boost/hana/fwd/and.hpp2
-rw-r--r--boost/hana/fwd/any.hpp2
-rw-r--r--boost/hana/fwd/any_of.hpp2
-rw-r--r--boost/hana/fwd/ap.hpp2
-rw-r--r--boost/hana/fwd/append.hpp2
-rw-r--r--boost/hana/fwd/at.hpp2
-rw-r--r--boost/hana/fwd/at_key.hpp2
-rw-r--r--boost/hana/fwd/back.hpp2
-rw-r--r--boost/hana/fwd/basic_tuple.hpp2
-rw-r--r--boost/hana/fwd/bool.hpp2
-rw-r--r--boost/hana/fwd/cartesian_product.hpp2
-rw-r--r--boost/hana/fwd/chain.hpp2
-rw-r--r--boost/hana/fwd/comparing.hpp2
-rw-r--r--boost/hana/fwd/concat.hpp2
-rw-r--r--boost/hana/fwd/concept/applicative.hpp2
-rw-r--r--boost/hana/fwd/concept/comonad.hpp2
-rw-r--r--boost/hana/fwd/concept/comparable.hpp2
-rw-r--r--boost/hana/fwd/concept/constant.hpp20
-rw-r--r--boost/hana/fwd/concept/euclidean_ring.hpp2
-rw-r--r--boost/hana/fwd/concept/foldable.hpp2
-rw-r--r--boost/hana/fwd/concept/functor.hpp2
-rw-r--r--boost/hana/fwd/concept/group.hpp2
-rw-r--r--boost/hana/fwd/concept/integral_constant.hpp2
-rw-r--r--boost/hana/fwd/concept/iterable.hpp2
-rw-r--r--boost/hana/fwd/concept/logical.hpp2
-rw-r--r--boost/hana/fwd/concept/metafunction.hpp2
-rw-r--r--boost/hana/fwd/concept/monad.hpp2
-rw-r--r--boost/hana/fwd/concept/monad_plus.hpp2
-rw-r--r--boost/hana/fwd/concept/monoid.hpp2
-rw-r--r--boost/hana/fwd/concept/orderable.hpp2
-rw-r--r--boost/hana/fwd/concept/product.hpp2
-rw-r--r--boost/hana/fwd/concept/ring.hpp2
-rw-r--r--boost/hana/fwd/concept/searchable.hpp2
-rw-r--r--boost/hana/fwd/concept/sequence.hpp2
-rw-r--r--boost/hana/fwd/concept/struct.hpp2
-rw-r--r--boost/hana/fwd/contains.hpp2
-rw-r--r--boost/hana/fwd/core.hpp2
-rw-r--r--boost/hana/fwd/core/common.hpp2
-rw-r--r--boost/hana/fwd/core/default.hpp2
-rw-r--r--boost/hana/fwd/core/is_a.hpp2
-rw-r--r--boost/hana/fwd/core/make.hpp2
-rw-r--r--boost/hana/fwd/core/tag_of.hpp2
-rw-r--r--boost/hana/fwd/core/to.hpp2
-rw-r--r--boost/hana/fwd/core/when.hpp2
-rw-r--r--boost/hana/fwd/count.hpp2
-rw-r--r--boost/hana/fwd/count_if.hpp2
-rw-r--r--boost/hana/fwd/cycle.hpp2
-rw-r--r--boost/hana/fwd/define_struct.hpp2
-rw-r--r--boost/hana/fwd/difference.hpp2
-rw-r--r--boost/hana/fwd/div.hpp2
-rw-r--r--boost/hana/fwd/drop_back.hpp2
-rw-r--r--boost/hana/fwd/drop_front.hpp2
-rw-r--r--boost/hana/fwd/drop_front_exactly.hpp2
-rw-r--r--boost/hana/fwd/drop_while.hpp2
-rw-r--r--boost/hana/fwd/duplicate.hpp2
-rw-r--r--boost/hana/fwd/empty.hpp2
-rw-r--r--boost/hana/fwd/equal.hpp2
-rw-r--r--boost/hana/fwd/erase_key.hpp2
-rw-r--r--boost/hana/fwd/eval.hpp2
-rw-r--r--boost/hana/fwd/eval_if.hpp2
-rw-r--r--boost/hana/fwd/extend.hpp2
-rw-r--r--boost/hana/fwd/extract.hpp2
-rw-r--r--boost/hana/fwd/fill.hpp2
-rw-r--r--boost/hana/fwd/filter.hpp2
-rw-r--r--boost/hana/fwd/find.hpp2
-rw-r--r--boost/hana/fwd/find_if.hpp2
-rw-r--r--boost/hana/fwd/first.hpp2
-rw-r--r--boost/hana/fwd/flatten.hpp2
-rw-r--r--boost/hana/fwd/fold.hpp2
-rw-r--r--boost/hana/fwd/fold_left.hpp2
-rw-r--r--boost/hana/fwd/fold_right.hpp2
-rw-r--r--boost/hana/fwd/for_each.hpp2
-rw-r--r--boost/hana/fwd/front.hpp2
-rw-r--r--boost/hana/fwd/fuse.hpp2
-rw-r--r--boost/hana/fwd/greater.hpp2
-rw-r--r--boost/hana/fwd/greater_equal.hpp2
-rw-r--r--boost/hana/fwd/group.hpp2
-rw-r--r--boost/hana/fwd/if.hpp2
-rw-r--r--boost/hana/fwd/insert.hpp2
-rw-r--r--boost/hana/fwd/insert_range.hpp2
-rw-r--r--boost/hana/fwd/integral_constant.hpp2
-rw-r--r--boost/hana/fwd/intersection.hpp2
-rw-r--r--boost/hana/fwd/intersperse.hpp2
-rw-r--r--boost/hana/fwd/is_disjoint.hpp2
-rw-r--r--boost/hana/fwd/is_empty.hpp2
-rw-r--r--boost/hana/fwd/is_subset.hpp2
-rw-r--r--boost/hana/fwd/keys.hpp2
-rw-r--r--boost/hana/fwd/lazy.hpp2
-rw-r--r--boost/hana/fwd/length.hpp2
-rw-r--r--boost/hana/fwd/less.hpp2
-rw-r--r--boost/hana/fwd/less_equal.hpp2
-rw-r--r--boost/hana/fwd/lexicographical_compare.hpp2
-rw-r--r--boost/hana/fwd/lift.hpp2
-rw-r--r--boost/hana/fwd/map.hpp21
-rw-r--r--boost/hana/fwd/max.hpp2
-rw-r--r--boost/hana/fwd/maximum.hpp2
-rw-r--r--boost/hana/fwd/members.hpp2
-rw-r--r--boost/hana/fwd/min.hpp2
-rw-r--r--boost/hana/fwd/minimum.hpp2
-rw-r--r--boost/hana/fwd/minus.hpp2
-rw-r--r--boost/hana/fwd/mod.hpp2
-rw-r--r--boost/hana/fwd/monadic_compose.hpp2
-rw-r--r--boost/hana/fwd/monadic_fold_left.hpp2
-rw-r--r--boost/hana/fwd/monadic_fold_right.hpp2
-rw-r--r--boost/hana/fwd/mult.hpp2
-rw-r--r--boost/hana/fwd/negate.hpp2
-rw-r--r--boost/hana/fwd/none.hpp2
-rw-r--r--boost/hana/fwd/none_of.hpp2
-rw-r--r--boost/hana/fwd/not.hpp2
-rw-r--r--boost/hana/fwd/not_equal.hpp2
-rw-r--r--boost/hana/fwd/one.hpp2
-rw-r--r--boost/hana/fwd/optional.hpp2
-rw-r--r--boost/hana/fwd/or.hpp2
-rw-r--r--boost/hana/fwd/ordering.hpp2
-rw-r--r--boost/hana/fwd/pair.hpp2
-rw-r--r--boost/hana/fwd/partition.hpp2
-rw-r--r--boost/hana/fwd/permutations.hpp2
-rw-r--r--boost/hana/fwd/plus.hpp2
-rw-r--r--boost/hana/fwd/power.hpp2
-rw-r--r--boost/hana/fwd/prefix.hpp2
-rw-r--r--boost/hana/fwd/prepend.hpp2
-rw-r--r--boost/hana/fwd/product.hpp2
-rw-r--r--boost/hana/fwd/range.hpp2
-rw-r--r--boost/hana/fwd/remove.hpp2
-rw-r--r--boost/hana/fwd/remove_at.hpp2
-rw-r--r--boost/hana/fwd/remove_if.hpp2
-rw-r--r--boost/hana/fwd/remove_range.hpp2
-rw-r--r--boost/hana/fwd/repeat.hpp2
-rw-r--r--boost/hana/fwd/replace.hpp2
-rw-r--r--boost/hana/fwd/replace_if.hpp2
-rw-r--r--boost/hana/fwd/replicate.hpp2
-rw-r--r--boost/hana/fwd/reverse.hpp2
-rw-r--r--boost/hana/fwd/reverse_fold.hpp2
-rw-r--r--boost/hana/fwd/scan_left.hpp2
-rw-r--r--boost/hana/fwd/scan_right.hpp2
-rw-r--r--boost/hana/fwd/second.hpp2
-rw-r--r--boost/hana/fwd/set.hpp6
-rw-r--r--boost/hana/fwd/size.hpp2
-rw-r--r--boost/hana/fwd/slice.hpp2
-rw-r--r--boost/hana/fwd/sort.hpp2
-rw-r--r--boost/hana/fwd/span.hpp2
-rw-r--r--boost/hana/fwd/string.hpp8
-rw-r--r--boost/hana/fwd/suffix.hpp2
-rw-r--r--boost/hana/fwd/sum.hpp2
-rw-r--r--boost/hana/fwd/symmetric_difference.hpp2
-rw-r--r--boost/hana/fwd/take_back.hpp2
-rw-r--r--boost/hana/fwd/take_front.hpp2
-rw-r--r--boost/hana/fwd/take_while.hpp2
-rw-r--r--boost/hana/fwd/tap.hpp2
-rw-r--r--boost/hana/fwd/then.hpp2
-rw-r--r--boost/hana/fwd/transform.hpp2
-rw-r--r--boost/hana/fwd/tuple.hpp2
-rw-r--r--boost/hana/fwd/type.hpp23
-rw-r--r--boost/hana/fwd/unfold_left.hpp2
-rw-r--r--boost/hana/fwd/unfold_right.hpp2
-rw-r--r--boost/hana/fwd/union.hpp2
-rw-r--r--boost/hana/fwd/unique.hpp2
-rw-r--r--boost/hana/fwd/unpack.hpp2
-rw-r--r--boost/hana/fwd/value.hpp2
-rw-r--r--boost/hana/fwd/while.hpp2
-rw-r--r--boost/hana/fwd/zero.hpp2
-rw-r--r--boost/hana/fwd/zip.hpp2
-rw-r--r--boost/hana/fwd/zip_shortest.hpp2
-rw-r--r--boost/hana/fwd/zip_shortest_with.hpp2
-rw-r--r--boost/hana/fwd/zip_with.hpp2
-rw-r--r--boost/hana/greater.hpp2
-rw-r--r--boost/hana/greater_equal.hpp2
-rw-r--r--boost/hana/group.hpp7
-rw-r--r--boost/hana/if.hpp6
-rw-r--r--boost/hana/insert.hpp2
-rw-r--r--boost/hana/insert_range.hpp2
-rw-r--r--boost/hana/integral_constant.hpp2
-rw-r--r--boost/hana/intersection.hpp2
-rw-r--r--boost/hana/intersperse.hpp2
-rw-r--r--boost/hana/is_disjoint.hpp2
-rw-r--r--boost/hana/is_empty.hpp2
-rw-r--r--boost/hana/is_subset.hpp2
-rw-r--r--boost/hana/keys.hpp2
-rw-r--r--boost/hana/lazy.hpp24
-rw-r--r--boost/hana/length.hpp2
-rw-r--r--boost/hana/less.hpp6
-rw-r--r--boost/hana/less_equal.hpp2
-rw-r--r--boost/hana/lexicographical_compare.hpp2
-rw-r--r--boost/hana/lift.hpp2
-rw-r--r--boost/hana/map.hpp142
-rw-r--r--boost/hana/max.hpp2
-rw-r--r--boost/hana/maximum.hpp2
-rw-r--r--boost/hana/members.hpp2
-rw-r--r--boost/hana/min.hpp2
-rw-r--r--boost/hana/minimum.hpp2
-rw-r--r--boost/hana/minus.hpp2
-rw-r--r--boost/hana/mod.hpp2
-rw-r--r--boost/hana/monadic_compose.hpp2
-rw-r--r--boost/hana/monadic_fold_left.hpp2
-rw-r--r--boost/hana/monadic_fold_right.hpp2
-rw-r--r--boost/hana/mult.hpp2
-rw-r--r--boost/hana/negate.hpp2
-rw-r--r--boost/hana/none.hpp2
-rw-r--r--boost/hana/none_of.hpp2
-rw-r--r--boost/hana/not.hpp2
-rw-r--r--boost/hana/not_equal.hpp2
-rw-r--r--boost/hana/one.hpp2
-rw-r--r--boost/hana/optional.hpp2
-rw-r--r--boost/hana/or.hpp2
-rw-r--r--boost/hana/ordering.hpp2
-rw-r--r--boost/hana/pair.hpp106
-rw-r--r--boost/hana/partition.hpp10
-rw-r--r--boost/hana/permutations.hpp2
-rw-r--r--boost/hana/plus.hpp2
-rw-r--r--boost/hana/power.hpp2
-rw-r--r--boost/hana/prefix.hpp2
-rw-r--r--boost/hana/prepend.hpp2
-rw-r--r--boost/hana/product.hpp2
-rw-r--r--boost/hana/range.hpp2
-rw-r--r--boost/hana/remove.hpp2
-rw-r--r--boost/hana/remove_at.hpp2
-rw-r--r--boost/hana/remove_if.hpp2
-rw-r--r--boost/hana/remove_range.hpp2
-rw-r--r--boost/hana/repeat.hpp2
-rw-r--r--boost/hana/replace.hpp2
-rw-r--r--boost/hana/replace_if.hpp2
-rw-r--r--boost/hana/replicate.hpp2
-rw-r--r--boost/hana/reverse.hpp2
-rw-r--r--boost/hana/reverse_fold.hpp2
-rw-r--r--boost/hana/scan_left.hpp2
-rw-r--r--boost/hana/scan_right.hpp2
-rw-r--r--boost/hana/second.hpp2
-rw-r--r--boost/hana/set.hpp3
-rw-r--r--boost/hana/size.hpp2
-rw-r--r--boost/hana/slice.hpp2
-rw-r--r--boost/hana/sort.hpp2
-rw-r--r--boost/hana/span.hpp2
-rw-r--r--boost/hana/string.hpp2
-rw-r--r--boost/hana/suffix.hpp2
-rw-r--r--boost/hana/sum.hpp2
-rw-r--r--boost/hana/symmetric_difference.hpp2
-rw-r--r--boost/hana/take_back.hpp8
-rw-r--r--boost/hana/take_front.hpp2
-rw-r--r--boost/hana/take_while.hpp2
-rw-r--r--boost/hana/tap.hpp2
-rw-r--r--boost/hana/then.hpp2
-rw-r--r--boost/hana/traits.hpp2
-rw-r--r--boost/hana/transform.hpp2
-rw-r--r--boost/hana/tuple.hpp37
-rw-r--r--boost/hana/type.hpp2
-rw-r--r--boost/hana/unfold_left.hpp2
-rw-r--r--boost/hana/unfold_right.hpp2
-rw-r--r--boost/hana/union.hpp2
-rw-r--r--boost/hana/unique.hpp2
-rw-r--r--boost/hana/unpack.hpp2
-rw-r--r--boost/hana/value.hpp2
-rw-r--r--boost/hana/version.hpp6
-rw-r--r--boost/hana/while.hpp2
-rw-r--r--boost/hana/zero.hpp2
-rw-r--r--boost/hana/zip.hpp2
-rw-r--r--boost/hana/zip_shortest.hpp2
-rw-r--r--boost/hana/zip_shortest_with.hpp7
-rw-r--r--boost/hana/zip_with.hpp2
-rw-r--r--boost/interprocess/detail/os_file_functions.hpp6
-rw-r--r--boost/interprocess/detail/os_thread_functions.hpp22
-rwxr-xr-xboost/interprocess/detail/shared_dir_helpers.hpp14
-rw-r--r--boost/interprocess/detail/utilities.hpp24
-rw-r--r--boost/interprocess/detail/win32_api.hpp205
-rw-r--r--boost/interprocess/offset_ptr.hpp130
-rw-r--r--boost/intrusive/bstree.hpp2
-rw-r--r--boost/intrusive/bstree_algorithms.hpp3
-rw-r--r--boost/intrusive/detail/key_nodeptr_comp.hpp14
-rw-r--r--boost/intrusive/slist.hpp2
-rw-r--r--boost/intrusive/treap.hpp2
-rw-r--r--boost/iostreams/chain.hpp20
-rw-r--r--boost/iostreams/code_converter.hpp8
-rw-r--r--boost/iostreams/detail/config/codecvt.hpp3
-rw-r--r--boost/iostreams/detail/config/fpos.hpp2
-rw-r--r--boost/iostreams/detail/config/unreachable_return.hpp1
-rw-r--r--boost/iostreams/detail/streambuf/indirect_streambuf.hpp39
-rw-r--r--boost/iostreams/device/mapped_file.hpp5
-rw-r--r--boost/iostreams/device/null.hpp2
-rw-r--r--boost/iostreams/filter/bzip2.hpp14
-rw-r--r--boost/iostreams/filter/gzip.hpp22
-rw-r--r--boost/iostreams/filter/symmetric.hpp7
-rw-r--r--boost/iostreams/filter/zlib.hpp34
-rw-r--r--boost/iostreams/invert.hpp4
-rw-r--r--boost/iterator/function_input_iterator.hpp10
-rw-r--r--boost/lexical_cast/detail/converter_lexical_streams.hpp7
-rw-r--r--boost/make_unique.hpp9
-rw-r--r--boost/math/special_functions/acosh.hpp2
-rw-r--r--boost/math/special_functions/asinh.hpp6
-rw-r--r--boost/math/special_functions/atanh.hpp6
-rw-r--r--boost/math/special_functions/bessel.hpp4
-rw-r--r--boost/math/special_functions/cbrt.hpp5
-rw-r--r--boost/math/special_functions/detail/bessel_i0.hpp585
-rw-r--r--boost/math/special_functions/detail/bessel_i1.hpp612
-rw-r--r--boost/math/special_functions/detail/bessel_k0.hpp557
-rw-r--r--boost/math/special_functions/detail/bessel_k1.hpp617
-rw-r--r--boost/math/special_functions/detail/bessel_kn.hpp8
-rw-r--r--boost/math/special_functions/erf.hpp8
-rw-r--r--boost/math/special_functions/expm1.hpp4
-rw-r--r--boost/math/special_functions/gamma.hpp8
-rw-r--r--boost/math/special_functions/log1p.hpp2
-rw-r--r--boost/math/special_functions/math_fwd.hpp11
-rw-r--r--boost/math/special_functions/next.hpp22
-rw-r--r--boost/math/tools/config.hpp2
-rw-r--r--boost/move/default_delete.hpp18
-rw-r--r--boost/move/detail/unique_ptr_meta_utils.hpp2
-rw-r--r--boost/multi_index/detail/archive_constructed.hpp6
-rw-r--r--boost/multi_index/detail/ignore_wstrict_aliasing.hpp18
-rw-r--r--boost/multi_index/detail/index_node_base.hpp6
-rw-r--r--boost/multi_index/detail/promotes_arg.hpp10
-rw-r--r--boost/multi_index/detail/restore_wstrict_aliasing.hpp11
-rw-r--r--boost/multi_index/detail/rnk_index_ops.hpp12
-rw-r--r--boost/multi_index/detail/seq_index_ops.hpp6
-rw-r--r--boost/multi_index/ranked_index.hpp10
-rw-r--r--boost/multiprecision/cpp_bin_float.hpp253
-rw-r--r--boost/multiprecision/cpp_bin_float/transcendental.hpp1
-rw-r--r--boost/multiprecision/cpp_dec_float.hpp41
-rw-r--r--boost/multiprecision/cpp_int/add.hpp4
-rw-r--r--boost/multiprecision/cpp_int/bitwise.hpp12
-rw-r--r--boost/multiprecision/cpp_int/divide.hpp2
-rw-r--r--boost/multiprecision/cpp_int/import_export.hpp8
-rw-r--r--boost/multiprecision/cpp_int/limits.hpp4
-rw-r--r--boost/multiprecision/cpp_int/multiply.hpp4
-rw-r--r--boost/multiprecision/debug_adaptor.hpp9
-rw-r--r--boost/multiprecision/detail/bitscan.hpp32
-rw-r--r--boost/multiprecision/detail/default_ops.hpp96
-rw-r--r--boost/multiprecision/detail/functions/pow.hpp164
-rw-r--r--boost/multiprecision/detail/functions/trig.hpp65
-rw-r--r--boost/multiprecision/float128.hpp20
-rw-r--r--boost/multiprecision/logged_adaptor.hpp7
-rw-r--r--boost/multiprecision/mpfi.hpp8
-rw-r--r--boost/multiprecision/mpfr.hpp32
-rw-r--r--boost/multiprecision/number.hpp76
-rw-r--r--boost/numeric/interval/hw_rounding.hpp4
-rw-r--r--boost/pool/pool_alloc.hpp24
-rw-r--r--boost/predef/compiler/intel.h11
-rw-r--r--boost/predef/compiler/visualc.h16
-rw-r--r--boost/predef/version.h2
-rw-r--r--boost/predef/version_number.h21
-rw-r--r--boost/preprocessor/cat.hpp2
-rw-r--r--boost/preprocessor/config/config.hpp10
-rw-r--r--boost/preprocessor/seq/detail/binary_transform.hpp11
-rw-r--r--boost/preprocessor/seq/detail/to_list_msvc.hpp55
-rw-r--r--boost/preprocessor/seq/to_list.hpp12
-rw-r--r--boost/process.hpp41
-rw-r--r--boost/process/args.hpp279
-rw-r--r--boost/process/async.hpp130
-rw-r--r--boost/process/async_pipe.hpp215
-rw-r--r--boost/process/async_system.hpp142
-rw-r--r--boost/process/child.hpp147
-rw-r--r--boost/process/cmd.hpp122
-rw-r--r--boost/process/detail/async_handler.hpp117
-rw-r--r--boost/process/detail/basic_cmd.hpp292
-rw-r--r--boost/process/detail/child_decl.hpp243
-rw-r--r--boost/process/detail/config.hpp99
-rw-r--r--boost/process/detail/execute_impl.hpp284
-rw-r--r--boost/process/detail/handler.hpp75
-rw-r--r--boost/process/detail/handler_base.hpp49
-rw-r--r--boost/process/detail/on_exit.hpp53
-rw-r--r--boost/process/detail/posix/asio_fwd.hpp79
-rw-r--r--boost/process/detail/posix/async_handler.hpp40
-rw-r--r--boost/process/detail/posix/async_in.hpp95
-rw-r--r--boost/process/detail/posix/async_out.hpp170
-rw-r--r--boost/process/detail/posix/async_pipe.hpp355
-rw-r--r--boost/process/detail/posix/basic_cmd.hpp177
-rw-r--r--boost/process/detail/posix/basic_pipe.hpp193
-rw-r--r--boost/process/detail/posix/child_handle.hpp60
-rw-r--r--boost/process/detail/posix/close_in.hpp30
-rw-r--r--boost/process/detail/posix/close_out.hpp55
-rw-r--r--boost/process/detail/posix/cmd.hpp104
-rw-r--r--boost/process/detail/posix/compare_handles.hpp42
-rw-r--r--boost/process/detail/posix/env_init.hpp41
-rw-r--r--boost/process/detail/posix/environment.hpp322
-rw-r--r--boost/process/detail/posix/exe.hpp36
-rw-r--r--boost/process/detail/posix/executor.hpp547
-rw-r--r--boost/process/detail/posix/fd.hpp92
-rw-r--r--boost/process/detail/posix/file_descriptor.hpp76
-rw-r--r--boost/process/detail/posix/file_in.hpp40
-rw-r--r--boost/process/detail/posix/file_out.hpp65
-rw-r--r--boost/process/detail/posix/group_handle.hpp103
-rw-r--r--boost/process/detail/posix/group_ref.hpp52
-rw-r--r--boost/process/detail/posix/handler.hpp74
-rw-r--r--boost/process/detail/posix/io_service_ref.hpp155
-rw-r--r--boost/process/detail/posix/is_running.hpp78
-rw-r--r--boost/process/detail/posix/null_in.hpp35
-rw-r--r--boost/process/detail/posix/null_out.hpp58
-rw-r--r--boost/process/detail/posix/on_exit.hpp35
-rw-r--r--boost/process/detail/posix/pipe_in.hpp90
-rw-r--r--boost/process/detail/posix/pipe_out.hpp116
-rw-r--r--boost/process/detail/posix/search_path.hpp39
-rw-r--r--boost/process/detail/posix/shell_path.hpp32
-rw-r--r--boost/process/detail/posix/signal.hpp79
-rw-r--r--boost/process/detail/posix/start_dir.hpp38
-rw-r--r--boost/process/detail/posix/terminate.hpp44
-rw-r--r--boost/process/detail/posix/use_vfork.hpp33
-rw-r--r--boost/process/detail/posix/wait_for_exit.hpp205
-rw-r--r--boost/process/detail/posix/wait_group.hpp191
-rw-r--r--boost/process/detail/throw_on_error.hpp36
-rw-r--r--boost/process/detail/traits.hpp17
-rw-r--r--boost/process/detail/traits/async.hpp34
-rw-r--r--boost/process/detail/traits/cmd_or_exe.hpp85
-rw-r--r--boost/process/detail/traits/decl.hpp76
-rw-r--r--boost/process/detail/traits/env.hpp53
-rw-r--r--boost/process/detail/traits/error.hpp27
-rw-r--r--boost/process/detail/traits/group.hpp37
-rw-r--r--boost/process/detail/traits/wchar_t.hpp274
-rw-r--r--boost/process/detail/windows/asio_fwd.hpp71
-rw-r--r--boost/process/detail/windows/async_handler.hpp40
-rw-r--r--boost/process/detail/windows/async_in.hpp105
-rw-r--r--boost/process/detail/windows/async_out.hpp176
-rw-r--r--boost/process/detail/windows/async_pipe.hpp415
-rw-r--r--boost/process/detail/windows/basic_cmd.hpp164
-rw-r--r--boost/process/detail/windows/basic_pipe.hpp225
-rw-r--r--boost/process/detail/windows/child_handle.hpp98
-rw-r--r--boost/process/detail/windows/close_in.hpp31
-rw-r--r--boost/process/detail/windows/close_out.hpp53
-rw-r--r--boost/process/detail/windows/cmd.hpp49
-rw-r--r--boost/process/detail/windows/compare_handles.hpp41
-rw-r--r--boost/process/detail/windows/env_init.hpp54
-rw-r--r--boost/process/detail/windows/environment.hpp356
-rw-r--r--boost/process/detail/windows/executor.hpp259
-rw-r--r--boost/process/detail/windows/file_descriptor.hpp104
-rw-r--r--boost/process/detail/windows/file_in.hpp44
-rw-r--r--boost/process/detail/windows/file_out.hpp77
-rw-r--r--boost/process/detail/windows/group_handle.hpp191
-rw-r--r--boost/process/detail/windows/group_ref.hpp51
-rw-r--r--boost/process/detail/windows/handler.hpp20
-rw-r--r--boost/process/detail/windows/io_service_ref.hpp160
-rw-r--r--boost/process/detail/windows/is_running.hpp64
-rw-r--r--boost/process/detail/windows/job_workaround.hpp139
-rw-r--r--boost/process/detail/windows/locale.hpp103
-rw-r--r--boost/process/detail/windows/null_in.hpp41
-rw-r--r--boost/process/detail/windows/null_out.hpp75
-rw-r--r--boost/process/detail/windows/on_exit.hpp40
-rw-r--r--boost/process/detail/windows/pipe_in.hpp89
-rw-r--r--boost/process/detail/windows/pipe_out.hpp122
-rw-r--r--boost/process/detail/windows/search_path.hpp54
-rw-r--r--boost/process/detail/windows/shell_path.hpp53
-rw-r--r--boost/process/detail/windows/show_window.hpp39
-rw-r--r--boost/process/detail/windows/start_dir.hpp36
-rw-r--r--boost/process/detail/windows/terminate.hpp49
-rw-r--r--boost/process/detail/windows/wait_for_exit.hpp193
-rw-r--r--boost/process/detail/windows/wait_group.hpp121
-rw-r--r--boost/process/env.hpp502
-rw-r--r--boost/process/environment.hpp698
-rw-r--r--boost/process/error.hpp211
-rw-r--r--boost/process/exception.hpp30
-rw-r--r--boost/process/exe.hpp79
-rw-r--r--boost/process/extend.hpp339
-rw-r--r--boost/process/group.hpp228
-rw-r--r--boost/process/io.hpp551
-rw-r--r--boost/process/locale.hpp246
-rw-r--r--boost/process/pipe.hpp475
-rw-r--r--boost/process/posix.hpp75
-rw-r--r--boost/process/search_path.hpp54
-rw-r--r--boost/process/shell.hpp92
-rw-r--r--boost/process/spawn.hpp69
-rw-r--r--boost/process/start_dir.hpp110
-rw-r--r--boost/process/system.hpp154
-rw-r--r--boost/process/windows.hpp58
-rw-r--r--boost/python/converter/pyobject_type.hpp7
-rw-r--r--boost/python/detail/config.hpp31
-rw-r--r--boost/python/detail/exception_handler.hpp2
-rw-r--r--[-rwxr-xr-x]boost/python/detail/wrapper_base.hpp2
-rw-r--r--boost/python/errors.hpp2
-rw-r--r--boost/python/numpy.hpp3
-rw-r--r--boost/python/numpy/config.hpp78
-rw-r--r--boost/python/numpy/dtype.hpp7
-rw-r--r--boost/python/numpy/invoke_matching.hpp6
-rw-r--r--boost/python/numpy/matrix.hpp4
-rw-r--r--boost/python/numpy/ndarray.hpp79
-rw-r--r--boost/python/numpy/numpy_object_mgr_traits.hpp4
-rw-r--r--boost/python/numpy/scalars.hpp2
-rw-r--r--boost/python/numpy/ufunc.hpp9
-rw-r--r--boost/python/object/instance.hpp2
-rw-r--r--boost/qvm/all.hpp5
-rw-r--r--boost/qvm/detail/swizzle_traits.hpp73
-rw-r--r--boost/qvm/gen/mat_operations2.hpp174
-rw-r--r--boost/qvm/gen/mat_operations3.hpp187
-rw-r--r--boost/qvm/gen/mat_operations4.hpp204
-rw-r--r--boost/qvm/gen/swizzle2.hpp90
-rw-r--r--boost/qvm/gen/swizzle3.hpp342
-rw-r--r--boost/qvm/gen/swizzle4.hpp1170
-rw-r--r--boost/qvm/gen/vec_operations2.hpp34
-rw-r--r--boost/qvm/gen/vec_operations3.hpp35
-rw-r--r--boost/qvm/gen/vec_operations4.hpp36
-rw-r--r--boost/qvm/mat_index.hpp145
-rw-r--r--boost/qvm/mat_operations.hpp33
-rw-r--r--boost/qvm/mat_traits_defaults.hpp95
-rw-r--r--boost/qvm/quat_traits_defaults.hpp40
-rw-r--r--boost/qvm/scalar_traits.hpp1
-rw-r--r--boost/qvm/vec_index.hpp145
-rw-r--r--boost/qvm/vec_operations.hpp32
-rw-r--r--boost/qvm/vec_traits_defaults.hpp94
-rw-r--r--boost/random/detail/int_float_pair.hpp121
-rw-r--r--boost/random/exponential_distribution.hpp210
-rw-r--r--boost/random/normal_distribution.hpp163
-rw-r--r--boost/rational.hpp497
-rw-r--r--boost/regex/config.hpp6
-rw-r--r--boost/regex/icu.hpp2
-rw-r--r--boost/regex/pending/unicode_iterator.hpp5
-rw-r--r--boost/regex/v4/basic_regex_creator.hpp189
-rw-r--r--boost/regex/v4/basic_regex_parser.hpp11
-rw-r--r--boost/regex/v4/match_flags.hpp13
-rw-r--r--boost/regex/v4/perl_matcher.hpp5
-rw-r--r--boost/regex/v4/perl_matcher_common.hpp2
-rw-r--r--boost/regex/v4/perl_matcher_non_recursive.hpp86
-rw-r--r--boost/regex/v4/perl_matcher_recursive.hpp18
-rw-r--r--boost/regex/v4/regex_workaround.hpp1
-rw-r--r--boost/serialization/archive_input_unordered_map.hpp16
-rw-r--r--boost/serialization/archive_input_unordered_set.hpp17
-rw-r--r--boost/serialization/array.hpp150
-rw-r--r--boost/serialization/array_optimization.hpp37
-rw-r--r--boost/serialization/array_wrapper.hpp121
-rw-r--r--boost/serialization/boost_array.hpp33
-rw-r--r--boost/serialization/collections_load_imp.hpp3
-rw-r--r--boost/serialization/deque.hpp1
-rw-r--r--boost/serialization/detail/get_data.hpp59
-rw-r--r--boost/serialization/detail/stack_constructor.hpp4
-rw-r--r--boost/serialization/ephemeral.hpp1
-rw-r--r--boost/serialization/factory.hpp1
-rw-r--r--boost/serialization/forward_list.hpp12
-rw-r--r--boost/serialization/hash_map.hpp5
-rw-r--r--boost/serialization/hash_set.hpp5
-rw-r--r--boost/serialization/list.hpp1
-rw-r--r--boost/serialization/map.hpp7
-rw-r--r--boost/serialization/optional.hpp44
-rw-r--r--boost/serialization/priority_queue.hpp2
-rw-r--r--boost/serialization/queue.hpp2
-rw-r--r--boost/serialization/set.hpp7
-rw-r--r--boost/serialization/shared_ptr_helper.hpp7
-rw-r--r--boost/serialization/singleton.hpp22
-rw-r--r--boost/serialization/slist.hpp9
-rw-r--r--boost/serialization/stack.hpp2
-rw-r--r--boost/serialization/strong_typedef.hpp38
-rw-r--r--boost/serialization/unordered_collections_load_imp.hpp1
-rw-r--r--boost/serialization/valarray.hpp24
-rw-r--r--boost/serialization/vector.hpp16
-rw-r--r--boost/signals2/deconstruct.hpp2
-rw-r--r--boost/signals2/detail/auto_buffer.hpp4
-rw-r--r--boost/signals2/detail/signal_template.hpp1
-rw-r--r--boost/signals2/detail/signals_common_macros.hpp6
-rw-r--r--boost/signals2/detail/slot_template.hpp2
-rw-r--r--boost/signals2/detail/variadic_arg_type.hpp19
-rw-r--r--boost/smart_ptr/allocate_shared_array.hpp1163
-rw-r--r--boost/smart_ptr/detail/array_allocator.hpp318
-rw-r--r--boost/smart_ptr/detail/array_count_impl.hpp67
-rw-r--r--boost/smart_ptr/detail/array_traits.hpp60
-rw-r--r--boost/smart_ptr/detail/array_utility.hpp214
-rw-r--r--boost/smart_ptr/detail/shared_count.hpp62
-rw-r--r--boost/smart_ptr/detail/sp_counted_base.hpp2
-rw-r--r--boost/smart_ptr/detail/sp_counted_impl.hpp8
-rw-r--r--boost/smart_ptr/detail/sp_has_sync.hpp6
-rw-r--r--boost/smart_ptr/detail/sp_if_array.hpp34
-rw-r--r--boost/smart_ptr/detail/sp_noexcept.hpp30
-rw-r--r--boost/smart_ptr/enable_shared_from_this.hpp9
-rw-r--r--boost/smart_ptr/intrusive_ptr.hpp7
-rw-r--r--boost/smart_ptr/make_shared_array.hpp196
-rw-r--r--boost/smart_ptr/make_unique.hpp35
-rw-r--r--boost/smart_ptr/owner_less.hpp45
-rw-r--r--boost/smart_ptr/scoped_array.hpp3
-rw-r--r--boost/smart_ptr/scoped_ptr.hpp3
-rw-r--r--boost/smart_ptr/shared_array.hpp13
-rw-r--r--boost/smart_ptr/shared_ptr.hpp57
-rw-r--r--boost/smart_ptr/weak_ptr.hpp11
-rw-r--r--boost/system/cygwin_error.hpp6
-rw-r--r--boost/system/error_code.hpp17
-rw-r--r--boost/system/linux_error.hpp6
-rw-r--r--boost/system/system_error.hpp6
-rw-r--r--boost/system/windows_error.hpp6
-rw-r--r--boost/test/detail/throw_exception.hpp4
-rw-r--r--boost/test/execution_monitor.hpp19
-rw-r--r--boost/test/impl/compiler_log_formatter.ipp2
-rw-r--r--boost/test/impl/execution_monitor.ipp29
-rw-r--r--boost/test/impl/framework.ipp38
-rw-r--r--boost/test/impl/junit_log_formatter.ipp477
-rw-r--r--boost/test/impl/plain_report_formatter.ipp2
-rw-r--r--boost/test/impl/progress_monitor.ipp2
-rw-r--r--boost/test/impl/test_tools.ipp14
-rw-r--r--boost/test/impl/unit_test_log.ipp9
-rw-r--r--boost/test/impl/unit_test_main.ipp8
-rw-r--r--boost/test/impl/unit_test_monitor.ipp8
-rw-r--r--boost/test/impl/unit_test_parameters.ipp238
-rw-r--r--boost/test/output/junit_log_formatter.hpp44
-rw-r--r--boost/test/tools/detail/print_helper.hpp54
-rw-r--r--boost/test/unit_test_parameters.hpp53
-rw-r--r--boost/test/unit_test_suite.hpp30
-rw-r--r--boost/thread/detail/config.hpp2
-rw-r--r--boost/thread/detail/thread.hpp15
-rw-r--r--boost/thread/exceptions.hpp16
-rw-r--r--boost/thread/executors/executor.hpp2
-rw-r--r--boost/thread/executors/generic_executor_ref.hpp2
-rw-r--r--boost/thread/executors/loop_executor.hpp40
-rw-r--r--boost/thread/future.hpp4
-rw-r--r--boost/thread/futures/wait_for_all.hpp2
-rw-r--r--boost/thread/pthread/condition_variable_fwd.hpp16
-rw-r--r--boost/thread/pthread/timespec.hpp29
-rw-r--r--boost/thread/scoped_thread.hpp38
-rw-r--r--boost/thread/thread_functors.hpp21
-rw-r--r--boost/thread/thread_guard.hpp6
-rw-r--r--boost/thread/win32/interlocked_read.hpp151
-rw-r--r--boost/thread/win32/thread_primitives.hpp14
-rw-r--r--boost/type_index/runtime_cast/register_runtime_class.hpp62
-rw-r--r--boost/type_index/stl_type_index.hpp4
-rw-r--r--boost/type_traits.hpp1
-rw-r--r--boost/type_traits/detail/common_arithmetic_type.hpp6
-rw-r--r--boost/type_traits/is_rvalue_reference.hpp2
-rw-r--r--boost/type_traits/make_void.hpp52
-rw-r--r--boost/unordered/detail/allocate.hpp1393
-rw-r--r--boost/unordered/detail/buckets.hpp774
-rw-r--r--boost/unordered/detail/equivalent.hpp735
-rw-r--r--boost/unordered/detail/extract_key.hpp188
-rw-r--r--boost/unordered/detail/fwd.hpp34
-rw-r--r--boost/unordered/detail/implementation.hpp4986
-rw-r--r--boost/unordered/detail/map.hpp174
-rw-r--r--boost/unordered/detail/set.hpp168
-rw-r--r--boost/unordered/detail/table.hpp794
-rw-r--r--boost/unordered/detail/unique.hpp683
-rw-r--r--boost/unordered/detail/util.hpp249
-rw-r--r--boost/unordered/unordered_map.hpp3233
-rw-r--r--boost/unordered/unordered_map_fwd.hpp86
-rw-r--r--boost/unordered/unordered_set.hpp2826
-rw-r--r--boost/unordered/unordered_set_fwd.hpp84
-rw-r--r--boost/utility.hpp4
-rw-r--r--boost/utility/string_ref.hpp11
-rw-r--r--boost/utility/string_view.hpp25
-rw-r--r--boost/variant/polymorphic_get.hpp14
-rw-r--r--boost/variant/recursive_wrapper_fwd.hpp6
-rw-r--r--boost/variant/variant.hpp36
-rw-r--r--boost/variant/variant_fwd.hpp2
-rw-r--r--boost/version.hpp4
1602 files changed, 51319 insertions, 20416 deletions
diff --git a/boost/align.hpp b/boost/align.hpp
index 89eebe1a77..45fe36bbcc 100644
--- a/boost/align.hpp
+++ b/boost/align.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_HPP
#define BOOST_ALIGN_HPP
diff --git a/boost/align/align.hpp b/boost/align/align.hpp
index 3582dcc051..ee4371091c 100644
--- a/boost/align/align.hpp
+++ b/boost/align/align.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGN_HPP
#define BOOST_ALIGN_ALIGN_HPP
diff --git a/boost/align/align_down.hpp b/boost/align/align_down.hpp
index f437f8e5b3..355844f8aa 100644
--- a/boost/align/align_down.hpp
+++ b/boost/align/align_down.hpp
@@ -1,27 +1,25 @@
/*
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGN_DOWN_HPP
#define BOOST_ALIGN_ALIGN_DOWN_HPP
#include <boost/align/detail/align_down.hpp>
-#include <boost/align/align_down_forward.hpp>
namespace boost {
namespace alignment {
-BOOST_CONSTEXPR inline std::size_t align_down(std::size_t value,
- std::size_t alignment) BOOST_NOEXCEPT
+BOOST_CONSTEXPR inline std::size_t
+align_down(std::size_t value, std::size_t alignment) BOOST_NOEXCEPT
{
return value & ~(alignment - 1);
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/align_down_forward.hpp b/boost/align/align_down_forward.hpp
deleted file mode 100644
index 6d124e8901..0000000000
--- a/boost/align/align_down_forward.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
-
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
-*/
-#ifndef BOOST_ALIGN_ALIGN_DOWN_FORWARD_HPP
-#define BOOST_ALIGN_ALIGN_DOWN_FORWARD_HPP
-
-#include <boost/config.hpp>
-#include <cstddef>
-
-namespace boost {
-namespace alignment {
-
-BOOST_CONSTEXPR std::size_t align_down(std::size_t value,
- std::size_t alignment) BOOST_NOEXCEPT;
-
-} /* .alignment */
-} /* .boost */
-
-#endif
diff --git a/boost/align/align_up.hpp b/boost/align/align_up.hpp
index b1cec1911e..6401ea848a 100644
--- a/boost/align/align_up.hpp
+++ b/boost/align/align_up.hpp
@@ -1,27 +1,25 @@
/*
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGN_UP_HPP
#define BOOST_ALIGN_ALIGN_UP_HPP
#include <boost/align/detail/align_up.hpp>
-#include <boost/align/align_up_forward.hpp>
namespace boost {
namespace alignment {
-BOOST_CONSTEXPR inline std::size_t align_up(std::size_t value,
- std::size_t alignment) BOOST_NOEXCEPT
+BOOST_CONSTEXPR inline std::size_t
+align_up(std::size_t value, std::size_t alignment) BOOST_NOEXCEPT
{
return (value + alignment - 1) & ~(alignment - 1);
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/align_up_forward.hpp b/boost/align/align_up_forward.hpp
deleted file mode 100644
index 47fdfcd0ba..0000000000
--- a/boost/align/align_up_forward.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
-
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
-*/
-#ifndef BOOST_ALIGN_ALIGN_UP_FORWARD_HPP
-#define BOOST_ALIGN_ALIGN_UP_FORWARD_HPP
-
-#include <boost/config.hpp>
-#include <cstddef>
-
-namespace boost {
-namespace alignment {
-
-BOOST_CONSTEXPR std::size_t align_up(std::size_t value,
- std::size_t alignment) BOOST_NOEXCEPT;
-
-} /* .alignment */
-} /* .boost */
-
-#endif
diff --git a/boost/align/aligned_alloc.hpp b/boost/align/aligned_alloc.hpp
index 7f2c0bb363..42128f1b24 100644
--- a/boost/align/aligned_alloc.hpp
+++ b/boost/align/aligned_alloc.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGNED_ALLOC_HPP
#define BOOST_ALIGN_ALIGNED_ALLOC_HPP
diff --git a/boost/align/aligned_allocator.hpp b/boost/align/aligned_allocator.hpp
index b70ed54230..6d0f788952 100644
--- a/boost/align/aligned_allocator.hpp
+++ b/boost/align/aligned_allocator.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_HPP
#define BOOST_ALIGN_ALIGNED_ALLOCATOR_HPP
@@ -74,12 +73,12 @@ public:
}
pointer allocate(size_type size, const_void_pointer = 0) {
- void* p = 0;
- if (size > 0) {
- p = aligned_alloc(min_align, sizeof(T) * size);
- if (!p) {
- boost::throw_exception(std::bad_alloc());
- }
+ if (size == 0) {
+ return 0;
+ }
+ void* p = aligned_alloc(min_align, sizeof(T) * size);
+ if (!p) {
+ boost::throw_exception(std::bad_alloc());
}
return static_cast<T*>(p);
}
@@ -139,21 +138,23 @@ public:
};
};
-template<class T1, class T2, std::size_t Alignment>
-inline bool operator==(const aligned_allocator<T1, Alignment>&,
- const aligned_allocator<T2, Alignment>&) BOOST_NOEXCEPT
+template<class T, class U, std::size_t Alignment>
+inline bool
+operator==(const aligned_allocator<T, Alignment>&,
+ const aligned_allocator<U, Alignment>&) BOOST_NOEXCEPT
{
return true;
}
-template<class T1, class T2, std::size_t Alignment>
-inline bool operator!=(const aligned_allocator<T1, Alignment>&,
- const aligned_allocator<T2, Alignment>&) BOOST_NOEXCEPT
+template<class T, class U, std::size_t Alignment>
+inline bool
+operator!=(const aligned_allocator<T, Alignment>&,
+ const aligned_allocator<U, Alignment>&) BOOST_NOEXCEPT
{
return false;
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/aligned_allocator_adaptor.hpp b/boost/align/aligned_allocator_adaptor.hpp
index b6ddd9c369..8905c215d3 100644
--- a/boost/align/aligned_allocator_adaptor.hpp
+++ b/boost/align/aligned_allocator_adaptor.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2016 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2016 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP
#define BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP
@@ -123,7 +122,8 @@ public:
char_ptr p = a.allocate(sizeof p + n);
void* r = detail::addressof(*p) + sizeof p;
(void)align(min_align, s, r, n);
- ::new((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);
}
@@ -142,12 +142,13 @@ public:
#endif
void* r = detail::addressof(*p) + sizeof p;
(void)align(min_align, s, r, n);
- ::new((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);
}
void deallocate(pointer ptr, size_type size) {
- char_ptr* p = (char_ptr*)ptr - 1;
+ char_ptr* p = reinterpret_cast<char_ptr*>(ptr) - 1;
char_ptr r = *p;
p->~char_ptr();
char_alloc a(base());
@@ -156,23 +157,23 @@ public:
}
};
-template<class A1, class A2, std::size_t Alignment>
-inline bool operator==(const aligned_allocator_adaptor<A1,
- Alignment>& a, const aligned_allocator_adaptor<A2,
- Alignment>& b) BOOST_NOEXCEPT
+template<class A, class B, std::size_t Alignment>
+inline bool
+operator==(const aligned_allocator_adaptor<A, Alignment>& a,
+ const aligned_allocator_adaptor<B, Alignment>& b) BOOST_NOEXCEPT
{
return a.base() == b.base();
}
-template<class A1, class A2, std::size_t Alignment>
-inline bool operator!=(const aligned_allocator_adaptor<A1,
- Alignment>& a, const aligned_allocator_adaptor<A2,
- Alignment>& b) BOOST_NOEXCEPT
+template<class A, class B, std::size_t Alignment>
+inline bool
+operator!=(const aligned_allocator_adaptor<A, Alignment>& a,
+ const aligned_allocator_adaptor<B, Alignment>& b) BOOST_NOEXCEPT
{
return !(a == b);
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/aligned_allocator_adaptor_forward.hpp b/boost/align/aligned_allocator_adaptor_forward.hpp
index d606f09920..f762cd1c3a 100644
--- a/boost/align/aligned_allocator_adaptor_forward.hpp
+++ b/boost/align/aligned_allocator_adaptor_forward.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_FORWARD_HPP
#define BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_FORWARD_HPP
@@ -17,7 +16,7 @@ namespace alignment {
template<class Allocator, std::size_t Alignment = 1>
class aligned_allocator_adaptor;
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/aligned_allocator_forward.hpp b/boost/align/aligned_allocator_forward.hpp
index 41f917f38c..23add71aaa 100644
--- a/boost/align/aligned_allocator_forward.hpp
+++ b/boost/align/aligned_allocator_forward.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_FORWARD_HPP
#define BOOST_ALIGN_ALIGNED_ALLOCATOR_FORWARD_HPP
@@ -17,7 +16,7 @@ namespace alignment {
template<class T, std::size_t Alignment = 1>
class aligned_allocator;
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/aligned_delete.hpp b/boost/align/aligned_delete.hpp
index 97b1c4b6ad..385bd557af 100644
--- a/boost/align/aligned_delete.hpp
+++ b/boost/align/aligned_delete.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGNED_DELETE_HPP
#define BOOST_ALIGN_ALIGNED_DELETE_HPP
@@ -26,7 +25,7 @@ struct aligned_delete {
}
};
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/aligned_delete_forward.hpp b/boost/align/aligned_delete_forward.hpp
index 7334bebdef..d5b766d7f0 100644
--- a/boost/align/aligned_delete_forward.hpp
+++ b/boost/align/aligned_delete_forward.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGNED_DELETE_FORWARD_HPP
#define BOOST_ALIGN_ALIGNED_DELETE_FORWARD_HPP
@@ -14,7 +13,7 @@ namespace alignment {
struct aligned_delete;
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/alignment_of.hpp b/boost/align/alignment_of.hpp
index 3dd2eb5b41..488df0b9e0 100644
--- a/boost/align/alignment_of.hpp
+++ b/boost/align/alignment_of.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2016 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2016 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGNMENT_OF_HPP
#define BOOST_ALIGN_ALIGNMENT_OF_HPP
@@ -39,14 +38,15 @@ namespace alignment {
template<class T>
struct alignment_of
- : detail::alignment_of<typename detail::element_type<T>::type> { };
+ : detail::alignment_of<typename
+ detail::element_type<T>::type>::type { };
#if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
template<class T>
constexpr std::size_t alignment_of_v = alignment_of<T>::value;
#endif
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/alignment_of_forward.hpp b/boost/align/alignment_of_forward.hpp
index 7ab227528b..31db15f23c 100644
--- a/boost/align/alignment_of_forward.hpp
+++ b/boost/align/alignment_of_forward.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGNMENT_OF_FORWARD_HPP
#define BOOST_ALIGN_ALIGNMENT_OF_FORWARD_HPP
@@ -15,7 +14,7 @@ namespace alignment {
template<class T>
struct alignment_of;
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/assume_aligned.hpp b/boost/align/assume_aligned.hpp
index 8d9f6ccf43..22e5103654 100644
--- a/boost/align/assume_aligned.hpp
+++ b/boost/align/assume_aligned.hpp
@@ -1,13 +1,12 @@
/*
-(c) 2015 NumScale SAS
-(c) 2015 LRI UMR 8623 CNRS/University Paris Sud XI
+Copyright 2015 NumScale SAS
+Copyright 2015 LRI UMR 8623 CNRS/University Paris Sud XI
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ASSUME_ALIGNED_HPP
#define BOOST_ALIGN_ASSUME_ALIGNED_HPP
diff --git a/boost/align/detail/addressof.hpp b/boost/align/detail/addressof.hpp
index 50731a70d0..a314830bed 100644
--- a/boost/align/detail/addressof.hpp
+++ b/boost/align/detail/addressof.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ADDRESSOF_HPP
#define BOOST_ALIGN_DETAIL_ADDRESSOF_HPP
@@ -27,8 +26,8 @@ using std::addressof;
using boost::addressof;
#endif
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/align.hpp b/boost/align/detail/align.hpp
index 77055e0328..a58dcea747 100644
--- a/boost/align/detail/align.hpp
+++ b/boost/align/detail/align.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2016 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2016 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGN_HPP
#define BOOST_ALIGN_DETAIL_ALIGN_HPP
@@ -15,13 +14,14 @@ http://boost.org/LICENSE_1_0.txt
namespace boost {
namespace alignment {
-inline void* align(std::size_t alignment, std::size_t size,
- void*& ptr, std::size_t& space)
+inline void*
+align(std::size_t alignment, std::size_t size, void*& ptr,
+ std::size_t& space)
{
BOOST_ASSERT(detail::is_alignment(alignment));
if (size <= space) {
- char* p = (char*)(((std::size_t)ptr + alignment - 1) &
- ~(alignment - 1));
+ char* p = reinterpret_cast<char*>((reinterpret_cast<std::
+ size_t>(ptr) + alignment - 1) & ~(alignment - 1));
std::size_t n = space - (p - static_cast<char*>(ptr));
if (size <= n) {
ptr = p;
@@ -32,7 +32,7 @@ inline void* align(std::size_t alignment, std::size_t size,
return 0;
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/align_cxx11.hpp b/boost/align/detail/align_cxx11.hpp
index a95b84c70f..637541ab40 100644
--- a/boost/align/detail/align_cxx11.hpp
+++ b/boost/align/detail/align_cxx11.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGN_CXX11_HPP
#define BOOST_ALIGN_DETAIL_ALIGN_CXX11_HPP
@@ -16,7 +15,7 @@ namespace alignment {
using std::align;
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/align_down.hpp b/boost/align/detail/align_down.hpp
index 97e1c1d3eb..9a8c358c41 100644
--- a/boost/align/detail/align_down.hpp
+++ b/boost/align/detail/align_down.hpp
@@ -1,28 +1,28 @@
/*
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGN_DOWN_HPP
#define BOOST_ALIGN_DETAIL_ALIGN_DOWN_HPP
#include <boost/align/detail/is_alignment.hpp>
-#include <boost/align/align_down_forward.hpp>
#include <boost/assert.hpp>
namespace boost {
namespace alignment {
-inline void* align_down(void* ptr, std::size_t alignment) BOOST_NOEXCEPT
+inline void*
+align_down(void* ptr, std::size_t alignment) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
- return (void*)(align_down((std::size_t)ptr, alignment));
+ return reinterpret_cast<void*>(reinterpret_cast<std::
+ size_t>(ptr) & ~(alignment - 1));
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/align_up.hpp b/boost/align/detail/align_up.hpp
index e956f7a046..86686da6ae 100644
--- a/boost/align/detail/align_up.hpp
+++ b/boost/align/detail/align_up.hpp
@@ -1,28 +1,28 @@
/*
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGN_UP_HPP
#define BOOST_ALIGN_DETAIL_ALIGN_UP_HPP
#include <boost/align/detail/is_alignment.hpp>
-#include <boost/align/align_up_forward.hpp>
#include <boost/assert.hpp>
namespace boost {
namespace alignment {
-inline void* align_up(void* ptr, std::size_t alignment) BOOST_NOEXCEPT
+inline void*
+align_up(void* ptr, std::size_t alignment) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
- return (void*)(align_up((std::size_t)ptr, alignment));
+ return reinterpret_cast<void*>((reinterpret_cast<std::
+ size_t>(ptr) + alignment - 1) & ~(alignment - 1));
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/aligned_alloc.hpp b/boost/align/detail/aligned_alloc.hpp
index 0488847bbd..69da19659a 100644
--- a/boost/align/detail/aligned_alloc.hpp
+++ b/boost/align/detail/aligned_alloc.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_HPP
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_HPP
@@ -18,35 +17,36 @@ http://boost.org/LICENSE_1_0.txt
namespace boost {
namespace alignment {
-inline void* aligned_alloc(std::size_t alignment, std::size_t size)
- BOOST_NOEXCEPT
+inline void*
+aligned_alloc(std::size_t alignment, std::size_t size) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
enum {
- min_align = alignment_of<void*>::value
+ N = alignment_of<void*>::value
};
- if (alignment < min_align) {
- alignment = min_align;
+ if (alignment < N) {
+ alignment = N;
}
- std::size_t n = size + alignment - min_align;
- void* r = 0;
+ std::size_t n = size + alignment - N;
void* p = std::malloc(sizeof(void*) + n);
if (p) {
- r = static_cast<char*>(p) + sizeof p;
+ void* r = static_cast<char*>(p) + sizeof(void*);
(void)align(alignment, size, r, n);
*(static_cast<void**>(r) - 1) = p;
+ p = r;
}
- return r;
+ return p;
}
-inline void aligned_free(void* ptr) BOOST_NOEXCEPT
+inline void
+aligned_free(void* ptr) BOOST_NOEXCEPT
{
if (ptr) {
std::free(*(static_cast<void**>(ptr) - 1));
}
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/aligned_alloc_android.hpp b/boost/align/detail/aligned_alloc_android.hpp
index 0ed28a45eb..4119fbd9bc 100644
--- a/boost/align/detail/aligned_alloc_android.hpp
+++ b/boost/align/detail/aligned_alloc_android.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_ANDROID_HPP
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_ANDROID_HPP
@@ -16,19 +15,20 @@ http://boost.org/LICENSE_1_0.txt
namespace boost {
namespace alignment {
-inline void* aligned_alloc(std::size_t alignment, std::size_t size)
- BOOST_NOEXCEPT
+inline void*
+aligned_alloc(std::size_t alignment, std::size_t size) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
return ::memalign(alignment, size);
}
-inline void aligned_free(void* ptr) BOOST_NOEXCEPT
+inline void
+aligned_free(void* ptr) BOOST_NOEXCEPT
{
::free(ptr);
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/aligned_alloc_macos.hpp b/boost/align/detail/aligned_alloc_macos.hpp
index 0bdb7c2eb1..76366fa5c1 100644
--- a/boost/align/detail/aligned_alloc_macos.hpp
+++ b/boost/align/detail/aligned_alloc_macos.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MACOS_HPP
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MACOS_HPP
@@ -16,8 +15,8 @@ http://boost.org/LICENSE_1_0.txt
namespace boost {
namespace alignment {
-inline void* aligned_alloc(std::size_t alignment, std::size_t size)
- BOOST_NOEXCEPT
+inline void*
+aligned_alloc(std::size_t alignment, std::size_t size) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
if (size == 0) {
@@ -33,12 +32,13 @@ inline void* aligned_alloc(std::size_t alignment, std::size_t size)
return p;
}
-inline void aligned_free(void* ptr) BOOST_NOEXCEPT
+inline void
+aligned_free(void* ptr) BOOST_NOEXCEPT
{
::free(ptr);
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/aligned_alloc_msvc.hpp b/boost/align/detail/aligned_alloc_msvc.hpp
index abeccfc4e4..45c57c9915 100644
--- a/boost/align/detail/aligned_alloc_msvc.hpp
+++ b/boost/align/detail/aligned_alloc_msvc.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MSVC_HPP
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MSVC_HPP
@@ -16,19 +15,20 @@ http://boost.org/LICENSE_1_0.txt
namespace boost {
namespace alignment {
-inline void* aligned_alloc(std::size_t alignment, std::size_t size)
- BOOST_NOEXCEPT
+inline void*
+aligned_alloc(std::size_t alignment, std::size_t size) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
return ::_aligned_malloc(size, alignment);
}
-inline void aligned_free(void* ptr) BOOST_NOEXCEPT
+inline void
+aligned_free(void* ptr) BOOST_NOEXCEPT
{
::_aligned_free(ptr);
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/aligned_alloc_posix.hpp b/boost/align/detail/aligned_alloc_posix.hpp
index 931b0c4bd6..78fc842d20 100644
--- a/boost/align/detail/aligned_alloc_posix.hpp
+++ b/boost/align/detail/aligned_alloc_posix.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_POSIX_HPP
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_POSIX_HPP
@@ -16,8 +15,8 @@ http://boost.org/LICENSE_1_0.txt
namespace boost {
namespace alignment {
-inline void* aligned_alloc(std::size_t alignment, std::size_t size)
- BOOST_NOEXCEPT
+inline void*
+aligned_alloc(std::size_t alignment, std::size_t size) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
if (alignment < sizeof(void*)) {
@@ -30,12 +29,13 @@ inline void* aligned_alloc(std::size_t alignment, std::size_t size)
return p;
}
-inline void aligned_free(void* ptr) BOOST_NOEXCEPT
+inline void
+aligned_free(void* ptr) BOOST_NOEXCEPT
{
::free(ptr);
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/aligned_alloc_sunos.hpp b/boost/align/detail/aligned_alloc_sunos.hpp
index 5039c733c6..0948b40e39 100644
--- a/boost/align/detail/aligned_alloc_sunos.hpp
+++ b/boost/align/detail/aligned_alloc_sunos.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_SUNOS_HPP
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_SUNOS_HPP
@@ -16,19 +15,20 @@ http://boost.org/LICENSE_1_0.txt
namespace boost {
namespace alignment {
-inline void* aligned_alloc(std::size_t alignment, std::size_t size)
- BOOST_NOEXCEPT
+inline void*
+aligned_alloc(std::size_t alignment, std::size_t size) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
return ::memalign(alignment, size);
}
-inline void aligned_free(void* ptr) BOOST_NOEXCEPT
+inline void
+aligned_free(void* ptr) BOOST_NOEXCEPT
{
::free(ptr);
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/alignment_of.hpp b/boost/align/detail/alignment_of.hpp
index f3f6192899..b6fc3dcdcf 100644
--- a/boost/align/detail/alignment_of.hpp
+++ b/boost/align/detail/alignment_of.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_HPP
#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_HPP
@@ -16,17 +15,17 @@ namespace alignment {
namespace detail {
template<class T>
-struct alignof_helper {
+struct offset_value {
char value;
T object;
};
template<class T>
struct alignment_of
- : min_size<sizeof(T), sizeof(alignof_helper<T>) - sizeof(T)> { };
+ : min_size<sizeof(T), sizeof(offset_value<T>) - sizeof(T)> { };
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/alignment_of_clang.hpp b/boost/align/detail/alignment_of_clang.hpp
index f550156d73..95773e5ea3 100644
--- a/boost/align/detail/alignment_of_clang.hpp
+++ b/boost/align/detail/alignment_of_clang.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_CLANG_HPP
#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_CLANG_HPP
@@ -20,8 +19,8 @@ template<class T>
struct alignment_of
: integral_constant<std::size_t, __alignof(T)> { };
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/alignment_of_codegear.hpp b/boost/align/detail/alignment_of_codegear.hpp
index 8948309d88..ea6f904242 100644
--- a/boost/align/detail/alignment_of_codegear.hpp
+++ b/boost/align/detail/alignment_of_codegear.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_CODEGEAR_HPP
#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_CODEGEAR_HPP
@@ -20,8 +19,8 @@ template<class T>
struct alignment_of
: integral_constant<std::size_t, alignof(T)> { };
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/alignment_of_cxx11.hpp b/boost/align/detail/alignment_of_cxx11.hpp
index cbe2d9e7a8..05c7429385 100644
--- a/boost/align/detail/alignment_of_cxx11.hpp
+++ b/boost/align/detail/alignment_of_cxx11.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_CXX11_HPP
#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_CXX11_HPP
@@ -17,8 +16,8 @@ namespace detail {
using std::alignment_of;
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/alignment_of_gcc.hpp b/boost/align/detail/alignment_of_gcc.hpp
index ffd8294fe3..66a63a50b1 100644
--- a/boost/align/detail/alignment_of_gcc.hpp
+++ b/boost/align/detail/alignment_of_gcc.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_GCC_HPP
#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_GCC_HPP
@@ -20,8 +19,8 @@ template<class T>
struct alignment_of
: integral_constant<std::size_t, __alignof__(T)> { };
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/alignment_of_msvc.hpp b/boost/align/detail/alignment_of_msvc.hpp
index cdd7c477ce..1526c7c296 100644
--- a/boost/align/detail/alignment_of_msvc.hpp
+++ b/boost/align/detail/alignment_of_msvc.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_MSVC_HPP
#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_MSVC_HPP
@@ -16,7 +15,7 @@ namespace alignment {
namespace detail {
template<class T>
-struct alignof_helper {
+struct offset_value {
T first;
char value;
T second;
@@ -25,10 +24,10 @@ struct alignof_helper {
template<class T>
struct alignment_of
: min_size<sizeof(T),
- sizeof(alignof_helper<T>) - (sizeof(T) << 1)> { };
+ sizeof(offset_value<T>) - (sizeof(T) << 1)> { };
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/assume_aligned.hpp b/boost/align/detail/assume_aligned.hpp
index a1c632b94d..d218d8c64e 100644
--- a/boost/align/detail/assume_aligned.hpp
+++ b/boost/align/detail/assume_aligned.hpp
@@ -1,17 +1,16 @@
/*
-(c) 2015 NumScale SAS
-(c) 2015 LRI UMR 8623 CNRS/University Paris Sud XI
+Copyright 2015 NumScale SAS
+Copyright 2015 LRI UMR 8623 CNRS/University Paris Sud XI
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_HPP
#define BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_HPP
-#define BOOST_ALIGN_ASSUME_ALIGNED(p, n)
+#define BOOST_ALIGN_ASSUME_ALIGNED(ptr, alignment)
#endif
diff --git a/boost/align/detail/assume_aligned_clang.hpp b/boost/align/detail/assume_aligned_clang.hpp
index d57cf4f8e5..4c7159fa28 100644
--- a/boost/align/detail/assume_aligned_clang.hpp
+++ b/boost/align/detail/assume_aligned_clang.hpp
@@ -1,17 +1,16 @@
/*
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_CLANG_HPP
#define BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_CLANG_HPP
#if __has_builtin(__builtin_assume_aligned)
#define BOOST_ALIGN_ASSUME_ALIGNED(p, n) \
-(p) = (__typeof__(p))(__builtin_assume_aligned((p), (n)))
+(p) = static_cast<__typeof__(p)>(__builtin_assume_aligned((p), (n)))
#else
#define BOOST_ALIGN_ASSUME_ALIGNED(p, n)
#endif
diff --git a/boost/align/detail/assume_aligned_gcc.hpp b/boost/align/detail/assume_aligned_gcc.hpp
index fc6d76a07f..117344447a 100644
--- a/boost/align/detail/assume_aligned_gcc.hpp
+++ b/boost/align/detail/assume_aligned_gcc.hpp
@@ -1,18 +1,17 @@
/*
-(c) 2015 NumScale SAS
-(c) 2015 LRI UMR 8623 CNRS/University Paris Sud XI
+Copyright 2015 NumScale SAS
+Copyright 2015 LRI UMR 8623 CNRS/University Paris Sud XI
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_GCC_HPP
#define BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_GCC_HPP
#define BOOST_ALIGN_ASSUME_ALIGNED(p, n) \
-(p) = (__typeof__(p))(__builtin_assume_aligned((p), (n)))
+(p) = static_cast<__typeof__(p)>(__builtin_assume_aligned((p), (n)))
#endif
diff --git a/boost/align/detail/assume_aligned_intel.hpp b/boost/align/detail/assume_aligned_intel.hpp
index 1944f3de51..6792ce005c 100644
--- a/boost/align/detail/assume_aligned_intel.hpp
+++ b/boost/align/detail/assume_aligned_intel.hpp
@@ -1,18 +1,17 @@
/*
-(c) 2015 NumScale SAS
-(c) 2015 LRI UMR 8623 CNRS/University Paris Sud XI
+Copyright 2015 NumScale SAS
+Copyright 2015 LRI UMR 8623 CNRS/University Paris Sud XI
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_INTEL_HPP
#define BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_INTEL_HPP
-#define BOOST_ALIGN_ASSUME_ALIGNED(p, n) \
-__assume_aligned((p), (n))
+#define BOOST_ALIGN_ASSUME_ALIGNED(ptr, alignment) \
+__assume_aligned((ptr), (alignment))
#endif
diff --git a/boost/align/detail/assume_aligned_msvc.hpp b/boost/align/detail/assume_aligned_msvc.hpp
index e953333b02..75ac7e1242 100644
--- a/boost/align/detail/assume_aligned_msvc.hpp
+++ b/boost/align/detail/assume_aligned_msvc.hpp
@@ -1,20 +1,19 @@
/*
-(c) 2015 NumScale SAS
-(c) 2015 LRI UMR 8623 CNRS/University Paris Sud XI
+Copyright 2015 NumScale SAS
+Copyright 2015 LRI UMR 8623 CNRS/University Paris Sud XI
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_MSVC_HPP
#define BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_MSVC_HPP
#include <cstddef>
-#define BOOST_ALIGN_ASSUME_ALIGNED(p, n) \
-__assume(((std::size_t)(p) & ((n) - 1)) == 0)
+#define BOOST_ALIGN_ASSUME_ALIGNED(ptr, alignment) \
+__assume((reinterpret_cast<std::size_t>(ptr) & ((alignment) - 1)) == 0)
#endif
diff --git a/boost/align/detail/element_type.hpp b/boost/align/detail/element_type.hpp
index 69995e1613..5b2b732da0 100644
--- a/boost/align/detail/element_type.hpp
+++ b/boost/align/detail/element_type.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_ELEMENT_TYPE_HPP
#define BOOST_ALIGN_DETAIL_ELEMENT_TYPE_HPP
@@ -49,45 +48,44 @@ struct remove_all_extents {
};
template<class T>
-struct remove_all_extents<T[]>
- : remove_all_extents<T> { };
+struct remove_all_extents<T[]> {
+ typedef typename remove_all_extents<T>::type type;
+};
template<class T, std::size_t N>
-struct remove_all_extents<T[N]>
- : remove_all_extents<T> { };
+struct remove_all_extents<T[N]> {
+ typedef typename remove_all_extents<T>::type type;
+};
template<class T>
-struct remove_const {
+struct remove_cv {
typedef T type;
};
template<class T>
-struct remove_const<const T> {
+struct remove_cv<const T> {
typedef T type;
};
template<class T>
-struct remove_volatile {
+struct remove_cv<volatile T> {
typedef T type;
};
template<class T>
-struct remove_volatile<volatile T> {
+struct remove_cv<const volatile T> {
typedef T type;
};
-
-template<class T>
-struct remove_cv
- : remove_volatile<typename remove_const<T>::type> { };
#endif
template<class T>
-struct element_type
- : remove_cv<typename remove_all_extents<typename
- remove_reference<T>::type>::type> { };
+struct element_type {
+ typedef typename remove_cv<typename remove_all_extents<typename
+ remove_reference<T>::type>::type>::type type;
+};
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/integral_constant.hpp b/boost/align/detail/integral_constant.hpp
index 1ad67e330f..860096783e 100644
--- a/boost/align/detail/integral_constant.hpp
+++ b/boost/align/detail/integral_constant.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2016 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2016 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_INTEGRAL_CONSTANT_HPP
#define BOOST_ALIGN_DETAIL_INTEGRAL_CONSTANT_HPP
@@ -37,10 +36,13 @@ struct integral_constant {
BOOST_STATIC_CONSTEXPR T value = Value;
};
+
+template<class T, T Value>
+BOOST_CONSTEXPR_OR_CONST T integral_constant<T, Value>::value;
#endif
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/is_aligned.hpp b/boost/align/detail/is_aligned.hpp
index e7c7dd60a0..61982c4685 100644
--- a/boost/align/detail/is_aligned.hpp
+++ b/boost/align/detail/is_aligned.hpp
@@ -1,36 +1,34 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_IS_ALIGNED_HPP
#define BOOST_ALIGN_DETAIL_IS_ALIGNED_HPP
#include <boost/align/detail/is_alignment.hpp>
-#include <boost/align/is_aligned_forward.hpp>
#include <boost/assert.hpp>
namespace boost {
namespace alignment {
-inline bool is_aligned(const void* ptr, std::size_t alignment)
- BOOST_NOEXCEPT
+inline bool
+is_aligned(const void* ptr, std::size_t alignment) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
- return is_aligned((std::size_t)ptr, alignment);
+ return (reinterpret_cast<std::size_t>(ptr) & (alignment - 1)) == 0;
}
-inline bool is_aligned(std::size_t alignment, const void* ptr)
- BOOST_NOEXCEPT
+inline bool
+is_aligned(std::size_t alignment, const void* ptr) BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
- return is_aligned((std::size_t)ptr, alignment);
+ return (reinterpret_cast<std::size_t>(ptr) & (alignment - 1)) == 0;
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/is_alignment.hpp b/boost/align/detail/is_alignment.hpp
index 12d8df974f..8bedba19c3 100644
--- a/boost/align/detail/is_alignment.hpp
+++ b/boost/align/detail/is_alignment.hpp
@@ -1,10 +1,10 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
*/
#ifndef BOOST_ALIGN_DETAIL_IS_ALIGNMENT_HPP
#define BOOST_ALIGN_DETAIL_IS_ALIGNMENT_HPP
@@ -16,14 +16,14 @@ namespace boost {
namespace alignment {
namespace detail {
-BOOST_CONSTEXPR inline bool is_alignment(std::size_t value)
- BOOST_NOEXCEPT
+BOOST_CONSTEXPR inline bool
+is_alignment(std::size_t value) BOOST_NOEXCEPT
{
return (value > 0) && ((value & (value - 1)) == 0);
}
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/is_alignment_constant.hpp b/boost/align/detail/is_alignment_constant.hpp
index eb709b7bc2..0ded62857e 100644
--- a/boost/align/detail/is_alignment_constant.hpp
+++ b/boost/align/detail/is_alignment_constant.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_IS_ALIGNMENT_CONSTANT_HPP
#define BOOST_ALIGN_DETAIL_IS_ALIGNMENT_CONSTANT_HPP
@@ -20,8 +19,8 @@ template<std::size_t N>
struct is_alignment_constant
: integral_constant<bool, (N > 0) && ((N & (N - 1)) == 0)> { };
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/max_align.hpp b/boost/align/detail/max_align.hpp
index d91de0dab5..9c09fec9c9 100644
--- a/boost/align/detail/max_align.hpp
+++ b/boost/align/detail/max_align.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_MAX_ALIGN_HPP
#define BOOST_ALIGN_DETAIL_MAX_ALIGN_HPP
@@ -20,8 +19,8 @@ template<class A, class B>
struct max_align
: max_size<alignment_of<A>::value, alignment_of<B>::value> { };
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/max_objects.hpp b/boost/align/detail/max_objects.hpp
index 27d377c5c2..9fdd30e118 100644
--- a/boost/align/detail/max_objects.hpp
+++ b/boost/align/detail/max_objects.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_MAX_OBJECTS_HPP
#define BOOST_ALIGN_DETAIL_MAX_OBJECTS_HPP
@@ -21,8 +20,8 @@ struct max_objects
: integral_constant<std::size_t,
~static_cast<std::size_t>(0) / sizeof(T)> { };
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/max_size.hpp b/boost/align/detail/max_size.hpp
index 555aa2c258..22cefdbec5 100644
--- a/boost/align/detail/max_size.hpp
+++ b/boost/align/detail/max_size.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_MAX_SIZE_HPP
#define BOOST_ALIGN_DETAIL_MAX_SIZE_HPP
@@ -20,8 +19,8 @@ template<std::size_t A, std::size_t B>
struct max_size
: integral_constant<std::size_t, (A > B) ? A : B> { };
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/detail/min_size.hpp b/boost/align/detail/min_size.hpp
index b20d3cdeaf..5b478fdaf0 100644
--- a/boost/align/detail/min_size.hpp
+++ b/boost/align/detail/min_size.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_DETAIL_MIN_SIZE_HPP
#define BOOST_ALIGN_DETAIL_MIN_SIZE_HPP
@@ -20,8 +19,8 @@ template<std::size_t A, std::size_t B>
struct min_size
: integral_constant<std::size_t, (A < B) ? A : B> { };
-} /* .detail */
-} /* .alignment */
-} /* .boost */
+} /* detail */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/is_aligned.hpp b/boost/align/is_aligned.hpp
index cbace96077..c8266d0eae 100644
--- a/boost/align/is_aligned.hpp
+++ b/boost/align/is_aligned.hpp
@@ -1,27 +1,26 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
*/
#ifndef BOOST_ALIGN_IS_ALIGNED_HPP
#define BOOST_ALIGN_IS_ALIGNED_HPP
#include <boost/align/detail/is_aligned.hpp>
-#include <boost/align/is_aligned_forward.hpp>
namespace boost {
namespace alignment {
-BOOST_CONSTEXPR inline bool is_aligned(std::size_t value,
- std::size_t alignment) BOOST_NOEXCEPT
+BOOST_CONSTEXPR inline bool
+is_aligned(std::size_t value, std::size_t alignment) BOOST_NOEXCEPT
{
return (value & (alignment - 1)) == 0;
}
-} /* .alignment */
-} /* .boost */
+} /* alignment */
+} /* boost */
#endif
diff --git a/boost/align/is_aligned_forward.hpp b/boost/align/is_aligned_forward.hpp
deleted file mode 100644
index d1bcbc19dd..0000000000
--- a/boost/align/is_aligned_forward.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-(c) 2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
-
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
-*/
-#ifndef BOOST_ALIGN_IS_ALIGNED_FORWARD_HPP
-#define BOOST_ALIGN_IS_ALIGNED_FORWARD_HPP
-
-#include <boost/config.hpp>
-#include <cstddef>
-
-namespace boost {
-namespace alignment {
-
-BOOST_CONSTEXPR bool is_aligned(std::size_t value,
- std::size_t alignment) BOOST_NOEXCEPT;
-
-} /* .alignment */
-} /* .boost */
-
-#endif
diff --git a/boost/any.hpp b/boost/any.hpp
index 437de2c023..9f6b313274 100644
--- a/boost/any.hpp
+++ b/boost/any.hpp
@@ -16,7 +16,7 @@
#include <algorithm>
-#include "boost/config.hpp"
+#include <boost/config.hpp>
#include <boost/type_index.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/decay.hpp>
@@ -27,6 +27,7 @@
#include <boost/throw_exception.hpp>
#include <boost/static_assert.hpp>
#include <boost/utility/enable_if.hpp>
+#include <boost/core/addressof.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/mpl/if.hpp>
@@ -244,7 +245,9 @@ namespace boost
ValueType * any_cast(any * operand) BOOST_NOEXCEPT
{
return operand && operand->type() == boost::typeindex::type_id<ValueType>()
- ? &static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held
+ ? boost::addressof(
+ static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held
+ )
: 0;
}
@@ -260,7 +263,7 @@ namespace boost
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
- nonref * result = any_cast<nonref>(&operand);
+ nonref * result = any_cast<nonref>(boost::addressof(operand));
if(!result)
boost::throw_exception(bad_any_cast());
@@ -274,7 +277,14 @@ namespace boost
BOOST_DEDUCED_TYPENAME boost::add_reference<ValueType>::type
>::type ref_type;
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4172) // "returning address of local variable or temporary" but *result is not local!
+#endif
return static_cast<ref_type>(*result);
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
}
template<typename ValueType>
@@ -306,7 +316,9 @@ namespace boost
template<typename ValueType>
inline ValueType * unsafe_any_cast(any * operand) BOOST_NOEXCEPT
{
- return &static_cast<any::holder<ValueType> *>(operand->content)->held;
+ return boost::addressof(
+ static_cast<any::holder<ValueType> *>(operand->content)->held
+ );
}
template<typename ValueType>
diff --git a/boost/archive/basic_binary_iprimitive.hpp b/boost/archive/basic_binary_iprimitive.hpp
index 40f45d9c2f..665d3e81e1 100644
--- a/boost/archive/basic_binary_iprimitive.hpp
+++ b/boost/archive/basic_binary_iprimitive.hpp
@@ -50,7 +50,7 @@ namespace std{
//#include <boost/mpl/placeholders.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp>
-#include <boost/serialization/array.hpp>
+#include <boost/serialization/array_wrapper.hpp>
#include <boost/archive/basic_streambuf_locale_saver.hpp>
#include <boost/archive/codecvt_null.hpp>
diff --git a/boost/archive/basic_binary_oprimitive.hpp b/boost/archive/basic_binary_oprimitive.hpp
index 4b7f454b25..6dc770c60e 100644
--- a/boost/archive/basic_binary_oprimitive.hpp
+++ b/boost/archive/basic_binary_oprimitive.hpp
@@ -45,7 +45,7 @@ namespace std{
//#include <boost/mpl/placeholders.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp>
-#include <boost/serialization/array.hpp>
+#include <boost/serialization/array_wrapper.hpp>
#include <boost/archive/basic_streambuf_locale_saver.hpp>
#include <boost/archive/codecvt_null.hpp>
diff --git a/boost/archive/basic_text_oprimitive.hpp b/boost/archive/basic_text_oprimitive.hpp
index c9f8c59160..45f09358ec 100644
--- a/boost/archive/basic_text_oprimitive.hpp
+++ b/boost/archive/basic_text_oprimitive.hpp
@@ -175,8 +175,6 @@ protected:
template<class T>
void save(const T & t){
- boost::io::ios_flags_saver fs(os);
- boost::io::ios_precision_saver ps(os);
typename is_float<T>::type tf;
save_impl(t, tf);
}
diff --git a/boost/archive/basic_xml_iarchive.hpp b/boost/archive/basic_xml_iarchive.hpp
index a882df5615..e9f7482f74 100644
--- a/boost/archive/basic_xml_iarchive.hpp
+++ b/boost/archive/basic_xml_iarchive.hpp
@@ -89,8 +89,7 @@ protected:
// leaving the archive in an undetermined state
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
load_override(class_id_type & t);
- BOOST_ARCHIVE_OR_WARCHIVE_DECL void
- load_override(class_id_optional_type & /* t */){}
+ void load_override(class_id_optional_type & /* t */){}
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
load_override(object_id_type & t);
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
diff --git a/boost/archive/detail/iserializer.hpp b/boost/archive/detail/iserializer.hpp
index 6bec499bd2..6e02eec7c4 100644
--- a/boost/archive/detail/iserializer.hpp
+++ b/boost/archive/detail/iserializer.hpp
@@ -77,10 +77,10 @@ namespace std{
#include <boost/serialization/type_info_implementation.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/void_cast.hpp>
-#include <boost/serialization/array.hpp>
#include <boost/serialization/collection_size_type.hpp>
#include <boost/serialization/singleton.hpp>
#include <boost/serialization/wrapper.hpp>
+#include <boost/serialization/array_wrapper.hpp>
// the following is need only for dynamic cast of polymorphic pointers
#include <boost/archive/archive_exception.hpp>
@@ -588,7 +588,14 @@ struct load_array_type {
boost::archive::archive_exception::array_size_too_short
)
);
- ar >> serialization::make_array(static_cast<value_type*>(&t[0]),count);
+ // explict template arguments to pass intel C++ compiler
+ ar >> serialization::make_array<
+ value_type,
+ boost::serialization::collection_size_type
+ >(
+ static_cast<value_type *>(&t[0]),
+ count
+ );
}
};
diff --git a/boost/archive/detail/oserializer.hpp b/boost/archive/detail/oserializer.hpp
index 0f2e733c58..c120ec5507 100644
--- a/boost/archive/detail/oserializer.hpp
+++ b/boost/archive/detail/oserializer.hpp
@@ -56,8 +56,9 @@
#include <boost/serialization/type_info_implementation.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/void_cast.hpp>
-#include <boost/serialization/array.hpp>
#include <boost/serialization/collection_size_type.hpp>
+#include <boost/serialization/array_wrapper.hpp>
+
#include <boost/serialization/singleton.hpp>
#include <boost/archive/archive_exception.hpp>
@@ -501,7 +502,14 @@ struct save_array_type
);
boost::serialization::collection_size_type count(c);
ar << BOOST_SERIALIZATION_NVP(count);
- ar << serialization::make_array(static_cast<value_type const*>(&t[0]),count);
+ // explict template arguments to pass intel C++ compiler
+ ar << serialization::make_array<
+ const value_type,
+ boost::serialization::collection_size_type
+ >(
+ static_cast<const value_type *>(&t[0]),
+ count
+ );
}
};
diff --git a/boost/archive/detail/utf8_codecvt_facet.hpp b/boost/archive/detail/utf8_codecvt_facet.hpp
index dfbec6bdfd..a40104abea 100644
--- a/boost/archive/detail/utf8_codecvt_facet.hpp
+++ b/boost/archive/detail/utf8_codecvt_facet.hpp
@@ -9,11 +9,14 @@
#include <boost/config.hpp>
-// std::codecvt_utf8 doesn't seem to work for msvc
-// versions prior to MSVC 14.0
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#endif
-#if defined(_MSC_VER) && _MSC_VER < 1900 \
-|| defined( BOOST_NO_CXX11_HDR_CODECVT )
+// std::codecvt_utf8 doesn't seem to work for any versions of msvc
+
+#if defined(_MSC_VER) || defined(BOOST_NO_CXX11_HDR_CODECVT)
+ // use boost's utf8 codecvt facet
#include <boost/archive/detail/decl.hpp>
#define BOOST_UTF8_BEGIN_NAMESPACE \
namespace boost { namespace archive { namespace detail {
@@ -26,9 +29,11 @@
#undef BOOST_UTF8_DECL
#undef BOOST_UTF8_BEGIN_NAMESPACE
#else
+ // use the standard vendor supplied facet
#include <codecvt>
namespace boost { namespace archive { namespace detail {
typedef std::codecvt_utf8<wchar_t> utf8_codecvt_facet;
} } }
-#endif // BOOST_NO_CXX11_HDR_CODECVT
+#endif
+
#endif // BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP
diff --git a/boost/archive/iterators/mb_from_wchar.hpp b/boost/archive/iterators/mb_from_wchar.hpp
index d5110de28a..b6dc9b2151 100644
--- a/boost/archive/iterators/mb_from_wchar.hpp
+++ b/boost/archive/iterators/mb_from_wchar.hpp
@@ -26,6 +26,7 @@ namespace std{
using ::mbstate_t;
} // namespace std
#endif
+
#include <boost/archive/detail/utf8_codecvt_facet.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
diff --git a/boost/array.hpp b/boost/array.hpp
index fa06fa9a5f..210c072125 100644
--- a/boost/array.hpp
+++ b/boost/array.hpp
@@ -13,6 +13,7 @@
* accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
+ * 9 Jan 2013 - (mtc) Added constexpr
* 14 Apr 2012 - (mtc) Added support for boost::hash
* 28 Dec 2010 - (mtc) Added cbegin and cend (and crbegin and crend) for C++Ox compatibility.
* 10 Mar 2010 - (mtc) fill method added, matching resolution of the standard library working group.
@@ -42,12 +43,12 @@
#include <cstddef>
#include <stdexcept>
#include <boost/assert.hpp>
+#include <boost/static_assert.hpp>
#include <boost/swap.hpp>
// Handles broken standard libraries better than <iterator>
#include <boost/detail/iterator.hpp>
#include <boost/throw_exception.hpp>
-#include <boost/functional/hash_fwd.hpp>
#include <algorithm>
// FIXES for broken compilers
@@ -81,15 +82,9 @@ namespace boost {
const_iterator cend() const { return elems+N; }
// reverse iterator support
-#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
+#if !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310)
- // workaround for broken reverse_iterator in VC7
- typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator,
- reference, iterator, reference> > reverse_iterator;
- typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator,
- const_reference, iterator, reference> > const_reverse_iterator;
#elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
value_type, reference, iterator, difference_type> reverse_iterator;
@@ -120,19 +115,17 @@ namespace boost {
// operator[]
reference operator[](size_type i)
{
- BOOST_ASSERT_MSG( i < N, "out of range" );
- return elems[i];
+ return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i];
}
- const_reference operator[](size_type i) const
+ /*BOOST_CONSTEXPR*/ const_reference operator[](size_type i) const
{
- BOOST_ASSERT_MSG( i < N, "out of range" );
- return elems[i];
+ return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i];
}
// at() with range check
- reference at(size_type i) { rangecheck(i); return elems[i]; }
- const_reference at(size_type i) const { rangecheck(i); return elems[i]; }
+ reference at(size_type i) { return rangecheck(i), elems[i]; }
+ /*BOOST_CONSTEXPR*/ const_reference at(size_type i) const { return rangecheck(i), elems[i]; }
// front() and back()
reference front()
@@ -140,7 +133,7 @@ namespace boost {
return elems[0];
}
- const_reference front() const
+ BOOST_CONSTEXPR const_reference front() const
{
return elems[0];
}
@@ -150,15 +143,15 @@ namespace boost {
return elems[N-1];
}
- const_reference back() const
+ BOOST_CONSTEXPR const_reference back() const
{
return elems[N-1];
}
// size is constant
- static size_type size() { return N; }
- static bool empty() { return false; }
- static size_type max_size() { return N; }
+ static BOOST_CONSTEXPR size_type size() { return N; }
+ static BOOST_CONSTEXPR bool empty() { return false; }
+ static BOOST_CONSTEXPR size_type max_size() { return N; }
enum { static_size = N };
// swap (note: linear complexity)
@@ -189,16 +182,12 @@ namespace boost {
}
// check range (may be private because it is static)
- static void rangecheck (size_type i) {
- if (i >= size()) {
- std::out_of_range e("array<>: index out of range");
- boost::throw_exception(e);
- }
+ static BOOST_CONSTEXPR bool rangecheck (size_type i) {
+ return i > size() ? boost::throw_exception(std::out_of_range ("array<>: index out of range")), true : true;
}
};
-#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template< class T >
class array< T, 0 > {
@@ -222,15 +211,9 @@ namespace boost {
const_iterator cend() const { return cbegin(); }
// reverse iterator support
-#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
+#if !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310)
- // workaround for broken reverse_iterator in VC7
- typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator,
- reference, iterator, reference> > reverse_iterator;
- typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator,
- const_reference, iterator, reference> > const_reverse_iterator;
#elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
value_type, reference, iterator, difference_type> reverse_iterator;
@@ -264,14 +247,14 @@ namespace boost {
return failed_rangecheck();
}
- const_reference operator[](size_type /*i*/) const
+ /*BOOST_CONSTEXPR*/ const_reference operator[](size_type /*i*/) const
{
return failed_rangecheck();
}
// at() with range check
reference at(size_type /*i*/) { return failed_rangecheck(); }
- const_reference at(size_type /*i*/) const { return failed_rangecheck(); }
+ /*BOOST_CONSTEXPR*/ const_reference at(size_type /*i*/) const { return failed_rangecheck(); }
// front() and back()
reference front()
@@ -279,7 +262,7 @@ namespace boost {
return failed_rangecheck();
}
- const_reference front() const
+ BOOST_CONSTEXPR const_reference front() const
{
return failed_rangecheck();
}
@@ -289,15 +272,15 @@ namespace boost {
return failed_rangecheck();
}
- const_reference back() const
+ BOOST_CONSTEXPR const_reference back() const
{
return failed_rangecheck();
}
// size is constant
- static size_type size() { return 0; }
- static bool empty() { return true; }
- static size_type max_size() { return 0; }
+ static BOOST_CONSTEXPR size_type size() { return 0; }
+ static BOOST_CONSTEXPR bool empty() { return true; }
+ static BOOST_CONSTEXPR size_type max_size() { return 0; }
enum { static_size = 0 };
void swap (array<T,0>& /*y*/) {
@@ -335,7 +318,6 @@ namespace boost {
#endif
}
};
-#endif
// comparisons
template<class T, std::size_t N>
@@ -391,7 +373,7 @@ namespace boost {
// Specific for boost::array: simply returns its elems data member.
template <typename T, std::size_t N>
- typename const detail::c_array<T,N>::type& get_c_array(const boost::array<T,N>& arg)
+ typename detail::c_array<T,N>::type const& get_c_array(const boost::array<T,N>& arg)
{
return arg.elems;
}
@@ -429,6 +411,7 @@ namespace boost {
}
#endif
+ template <class It> std::size_t hash_range(It, It);
template<class T, std::size_t N>
std::size_t hash_value(const array<T,N>& arr)
@@ -436,8 +419,36 @@ namespace boost {
return boost::hash_range(arr.begin(), arr.end());
}
+ template <size_t Idx, typename T, size_t N>
+ T &get(boost::array<T,N> &arr) BOOST_NOEXCEPT {
+ BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(boost::array &) index out of range" );
+ return arr[Idx];
+ }
+
+ template <size_t Idx, typename T, size_t N>
+ const T &get(const boost::array<T,N> &arr) BOOST_NOEXCEPT {
+ BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(const boost::array &) index out of range" );
+ return arr[Idx];
+ }
+
} /* namespace boost */
+#ifndef BOOST_NO_CXX11_HDR_ARRAY
+// If we don't have std::array, I'm assuming that we don't have std::get
+namespace std {
+ template <size_t Idx, typename T, size_t N>
+ T &get(boost::array<T,N> &arr) BOOST_NOEXCEPT {
+ BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(boost::array &) index out of range" );
+ return arr[Idx];
+ }
+
+ template <size_t Idx, typename T, size_t N>
+ const T &get(const boost::array<T,N> &arr) BOOST_NOEXCEPT {
+ BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(const boost::array &) index out of range" );
+ return arr[Idx];
+ }
+}
+#endif
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
# pragma warning(pop)
diff --git a/boost/asio.hpp b/boost/asio.hpp
index 6523d60fe1..114d871c0c 100644
--- a/boost/asio.hpp
+++ b/boost/asio.hpp
@@ -2,7 +2,7 @@
// asio.hpp
// ~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/async_result.hpp b/boost/asio/async_result.hpp
index e5717b4159..6290b8462a 100644
--- a/boost/asio/async_result.hpp
+++ b/boost/asio/async_result.hpp
@@ -2,7 +2,7 @@
// async_result.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/basic_datagram_socket.hpp b/boost/asio/basic_datagram_socket.hpp
index d898a7f14b..22801ee081 100644
--- a/boost/asio/basic_datagram_socket.hpp
+++ b/boost/asio/basic_datagram_socket.hpp
@@ -2,7 +2,7 @@
// basic_datagram_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/basic_deadline_timer.hpp b/boost/asio/basic_deadline_timer.hpp
index b6c83f527e..930370046b 100644
--- a/boost/asio/basic_deadline_timer.hpp
+++ b/boost/asio/basic_deadline_timer.hpp
@@ -2,7 +2,7 @@
// basic_deadline_timer.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/basic_io_object.hpp b/boost/asio/basic_io_object.hpp
index 5912228ec7..d490a161f6 100644
--- a/boost/asio/basic_io_object.hpp
+++ b/boost/asio/basic_io_object.hpp
@@ -2,7 +2,7 @@
// basic_io_object.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -113,6 +113,11 @@ protected:
* @note Available only for services that support movability,
*/
basic_io_object& operator=(basic_io_object&& other);
+
+ /// Perform a converting move-construction of a basic_io_object.
+ template <typename IoObjectService1>
+ basic_io_object(IoObjectService1& other_service,
+ typename IoObjectService1::implementation_type& other_implementation);
#endif // defined(GENERATING_DOCUMENTATION)
/// Protected destructor to prevent deletion through this type.
@@ -192,6 +197,16 @@ protected:
service_->move_construct(implementation, other.implementation);
}
+ template <typename IoObjectService1>
+ basic_io_object(IoObjectService1& other_service,
+ typename IoObjectService1::implementation_type& other_implementation)
+ : service_(&boost::asio::use_service<IoObjectService>(
+ other_service.get_io_service()))
+ {
+ service_->converting_move_construct(implementation,
+ other_service, other_implementation);
+ }
+
~basic_io_object()
{
service_->destroy(implementation);
diff --git a/boost/asio/basic_raw_socket.hpp b/boost/asio/basic_raw_socket.hpp
index 2fe3e608b8..85f8f42642 100644
--- a/boost/asio/basic_raw_socket.hpp
+++ b/boost/asio/basic_raw_socket.hpp
@@ -2,7 +2,7 @@
// basic_raw_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/basic_seq_packet_socket.hpp b/boost/asio/basic_seq_packet_socket.hpp
index 4a2fec7556..c8e43f77d6 100644
--- a/boost/asio/basic_seq_packet_socket.hpp
+++ b/boost/asio/basic_seq_packet_socket.hpp
@@ -2,7 +2,7 @@
// basic_seq_packet_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/basic_serial_port.hpp b/boost/asio/basic_serial_port.hpp
index 7914457b62..bfc78afaf6 100644
--- a/boost/asio/basic_serial_port.hpp
+++ b/boost/asio/basic_serial_port.hpp
@@ -2,7 +2,7 @@
// basic_serial_port.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/basic_signal_set.hpp b/boost/asio/basic_signal_set.hpp
index cc26d6fab4..608bc0a6d8 100644
--- a/boost/asio/basic_signal_set.hpp
+++ b/boost/asio/basic_signal_set.hpp
@@ -2,7 +2,7 @@
// basic_signal_set.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/basic_socket.hpp b/boost/asio/basic_socket.hpp
index 64aef6fb2b..777f6a9ce1 100644
--- a/boost/asio/basic_socket.hpp
+++ b/boost/asio/basic_socket.hpp
@@ -2,7 +2,7 @@
// basic_socket.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -193,10 +193,9 @@ public:
template <typename Protocol1, typename SocketService1>
basic_socket(basic_socket<Protocol1, SocketService1>&& other,
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
- : basic_io_object<SocketService>(other.get_io_service())
+ : basic_io_object<SocketService>(
+ other.get_service(), other.get_implementation())
{
- this->get_service().template converting_move_construct<Protocol1>(
- this->get_implementation(), other.get_implementation());
}
/// Move-assign a basic_socket from a socket of another protocol type.
diff --git a/boost/asio/basic_socket_acceptor.hpp b/boost/asio/basic_socket_acceptor.hpp
index f39c407133..f1d2b8e7a6 100644
--- a/boost/asio/basic_socket_acceptor.hpp
+++ b/boost/asio/basic_socket_acceptor.hpp
@@ -2,7 +2,7 @@
// basic_socket_acceptor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -232,10 +232,9 @@ public:
basic_socket_acceptor(
basic_socket_acceptor<Protocol1, SocketAcceptorService1>&& other,
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
- : basic_io_object<SocketAcceptorService>(other.get_io_service())
+ : basic_io_object<SocketAcceptorService>(
+ other.get_service(), other.get_implementation())
{
- this->get_service().template converting_move_construct<Protocol1>(
- this->get_implementation(), other.get_implementation());
}
/// Move-assign a basic_socket_acceptor from an acceptor of another protocol
diff --git a/boost/asio/basic_socket_iostream.hpp b/boost/asio/basic_socket_iostream.hpp
index fd291f0f14..6ed71f7b68 100644
--- a/boost/asio/basic_socket_iostream.hpp
+++ b/boost/asio/basic_socket_iostream.hpp
@@ -2,7 +2,7 @@
// basic_socket_iostream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/basic_socket_streambuf.hpp b/boost/asio/basic_socket_streambuf.hpp
index 34052e47e4..922b005d88 100644
--- a/boost/asio/basic_socket_streambuf.hpp
+++ b/boost/asio/basic_socket_streambuf.hpp
@@ -2,7 +2,7 @@
// basic_socket_streambuf.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/basic_stream_socket.hpp b/boost/asio/basic_stream_socket.hpp
index 423a5c3de9..5b959d7db8 100644
--- a/boost/asio/basic_stream_socket.hpp
+++ b/boost/asio/basic_stream_socket.hpp
@@ -2,7 +2,7 @@
// basic_stream_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/basic_streambuf.hpp b/boost/asio/basic_streambuf.hpp
index 5c575dd676..1392596dc5 100644
--- a/boost/asio/basic_streambuf.hpp
+++ b/boost/asio/basic_streambuf.hpp
@@ -2,7 +2,7 @@
// basic_streambuf.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/basic_streambuf_fwd.hpp b/boost/asio/basic_streambuf_fwd.hpp
index 88e9549430..f3e006bf11 100644
--- a/boost/asio/basic_streambuf_fwd.hpp
+++ b/boost/asio/basic_streambuf_fwd.hpp
@@ -2,7 +2,7 @@
// basic_streambuf_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/basic_waitable_timer.hpp b/boost/asio/basic_waitable_timer.hpp
index a7293ee1dd..e4aeb0b7d8 100644
--- a/boost/asio/basic_waitable_timer.hpp
+++ b/boost/asio/basic_waitable_timer.hpp
@@ -2,7 +2,7 @@
// basic_waitable_timer.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/buffer.hpp b/boost/asio/buffer.hpp
index 4dd02d1125..700654d21d 100644
--- a/boost/asio/buffer.hpp
+++ b/boost/asio/buffer.hpp
@@ -2,7 +2,7 @@
// buffer.hpp
// ~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/buffered_read_stream.hpp b/boost/asio/buffered_read_stream.hpp
index 90e135e661..ece138b599 100644
--- a/boost/asio/buffered_read_stream.hpp
+++ b/boost/asio/buffered_read_stream.hpp
@@ -2,7 +2,7 @@
// buffered_read_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/buffered_read_stream_fwd.hpp b/boost/asio/buffered_read_stream_fwd.hpp
index 5c2af0db3b..3ffac04419 100644
--- a/boost/asio/buffered_read_stream_fwd.hpp
+++ b/boost/asio/buffered_read_stream_fwd.hpp
@@ -2,7 +2,7 @@
// buffered_read_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/buffered_stream.hpp b/boost/asio/buffered_stream.hpp
index 3c25b5f420..fae7c27113 100644
--- a/boost/asio/buffered_stream.hpp
+++ b/boost/asio/buffered_stream.hpp
@@ -2,7 +2,7 @@
// buffered_stream.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/buffered_stream_fwd.hpp b/boost/asio/buffered_stream_fwd.hpp
index 83498c043e..a1e965b25e 100644
--- a/boost/asio/buffered_stream_fwd.hpp
+++ b/boost/asio/buffered_stream_fwd.hpp
@@ -2,7 +2,7 @@
// buffered_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/buffered_write_stream.hpp b/boost/asio/buffered_write_stream.hpp
index f1b951cded..5b8f31378d 100644
--- a/boost/asio/buffered_write_stream.hpp
+++ b/boost/asio/buffered_write_stream.hpp
@@ -2,7 +2,7 @@
// buffered_write_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/buffered_write_stream_fwd.hpp b/boost/asio/buffered_write_stream_fwd.hpp
index 97b5a3e508..4759cf283c 100644
--- a/boost/asio/buffered_write_stream_fwd.hpp
+++ b/boost/asio/buffered_write_stream_fwd.hpp
@@ -2,7 +2,7 @@
// buffered_write_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/buffers_iterator.hpp b/boost/asio/buffers_iterator.hpp
index 70dc8741a6..c64b341b5b 100644
--- a/boost/asio/buffers_iterator.hpp
+++ b/boost/asio/buffers_iterator.hpp
@@ -2,7 +2,7 @@
// buffers_iterator.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/completion_condition.hpp b/boost/asio/completion_condition.hpp
index 7fbd0485aa..d64efffe1e 100644
--- a/boost/asio/completion_condition.hpp
+++ b/boost/asio/completion_condition.hpp
@@ -2,7 +2,7 @@
// completion_condition.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/connect.hpp b/boost/asio/connect.hpp
index 6275a5d0ec..635a8ad9bd 100644
--- a/boost/asio/connect.hpp
+++ b/boost/asio/connect.hpp
@@ -2,7 +2,7 @@
// connect.hpp
// ~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/coroutine.hpp b/boost/asio/coroutine.hpp
index 642b484bb1..c4763f8524 100644
--- a/boost/asio/coroutine.hpp
+++ b/boost/asio/coroutine.hpp
@@ -2,7 +2,7 @@
// coroutine.hpp
// ~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/datagram_socket_service.hpp b/boost/asio/datagram_socket_service.hpp
index 04a53671fc..95f179acfd 100644
--- a/boost/asio/datagram_socket_service.hpp
+++ b/boost/asio/datagram_socket_service.hpp
@@ -2,7 +2,7 @@
// datagram_socket_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -118,17 +118,21 @@ public:
service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
}
+ // All socket services have access to each other's implementations.
+ template <typename Protocol1> friend class datagram_socket_service;
+
/// Move-construct a new datagram socket implementation from another protocol
/// type.
template <typename Protocol1>
void converting_move_construct(implementation_type& impl,
+ datagram_socket_service<Protocol1>& other_service,
typename datagram_socket_service<
Protocol1>::implementation_type& other_impl,
typename enable_if<is_convertible<
Protocol1, Protocol>::value>::type* = 0)
{
service_impl_.template converting_move_construct<Protocol1>(
- impl, other_impl);
+ impl, other_service.service_impl_, other_impl);
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
diff --git a/boost/asio/deadline_timer.hpp b/boost/asio/deadline_timer.hpp
index 849ff65a29..f7be6be943 100644
--- a/boost/asio/deadline_timer.hpp
+++ b/boost/asio/deadline_timer.hpp
@@ -2,7 +2,7 @@
// deadline_timer.hpp
// ~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/deadline_timer_service.hpp b/boost/asio/deadline_timer_service.hpp
index 20ae802658..26dcb42e4c 100644
--- a/boost/asio/deadline_timer_service.hpp
+++ b/boost/asio/deadline_timer_service.hpp
@@ -2,7 +2,7 @@
// deadline_timer_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/addressof.hpp b/boost/asio/detail/addressof.hpp
index 972c1f1285..cc1099764d 100644
--- a/boost/asio/detail/addressof.hpp
+++ b/boost/asio/detail/addressof.hpp
@@ -2,7 +2,7 @@
// detail/addressof.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/array.hpp b/boost/asio/detail/array.hpp
index 2165e60438..29e5077412 100644
--- a/boost/asio/detail/array.hpp
+++ b/boost/asio/detail/array.hpp
@@ -2,7 +2,7 @@
// detail/array.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/array_fwd.hpp b/boost/asio/detail/array_fwd.hpp
index 6ba840a4e5..aefe467119 100644
--- a/boost/asio/detail/array_fwd.hpp
+++ b/boost/asio/detail/array_fwd.hpp
@@ -2,7 +2,7 @@
// detail/array_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/assert.hpp b/boost/asio/detail/assert.hpp
index 1254b8878c..b522552387 100644
--- a/boost/asio/detail/assert.hpp
+++ b/boost/asio/detail/assert.hpp
@@ -2,7 +2,7 @@
// detail/assert.hpp
// ~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/atomic_count.hpp b/boost/asio/detail/atomic_count.hpp
index 12e1ae9da7..416ed9d097 100644
--- a/boost/asio/detail/atomic_count.hpp
+++ b/boost/asio/detail/atomic_count.hpp
@@ -2,7 +2,7 @@
// detail/atomic_count.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/base_from_completion_cond.hpp b/boost/asio/detail/base_from_completion_cond.hpp
index b92c6992bb..61315ca0fb 100644
--- a/boost/asio/detail/base_from_completion_cond.hpp
+++ b/boost/asio/detail/base_from_completion_cond.hpp
@@ -2,7 +2,7 @@
// detail/base_from_completion_cond.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/bind_handler.hpp b/boost/asio/detail/bind_handler.hpp
index e73180474f..0f3672edab 100644
--- a/boost/asio/detail/bind_handler.hpp
+++ b/boost/asio/detail/bind_handler.hpp
@@ -2,7 +2,7 @@
// detail/bind_handler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/buffer_resize_guard.hpp b/boost/asio/detail/buffer_resize_guard.hpp
index 88b931519b..849defbec1 100644
--- a/boost/asio/detail/buffer_resize_guard.hpp
+++ b/boost/asio/detail/buffer_resize_guard.hpp
@@ -2,7 +2,7 @@
// detail/buffer_resize_guard.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/buffer_sequence_adapter.hpp b/boost/asio/detail/buffer_sequence_adapter.hpp
index fdca995413..20c529e0a2 100644
--- a/boost/asio/detail/buffer_sequence_adapter.hpp
+++ b/boost/asio/detail/buffer_sequence_adapter.hpp
@@ -2,7 +2,7 @@
// detail/buffer_sequence_adapter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/buffered_stream_storage.hpp b/boost/asio/detail/buffered_stream_storage.hpp
index 862c3526db..0ac5749eeb 100644
--- a/boost/asio/detail/buffered_stream_storage.hpp
+++ b/boost/asio/detail/buffered_stream_storage.hpp
@@ -2,7 +2,7 @@
// detail/buffered_stream_storage.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/call_stack.hpp b/boost/asio/detail/call_stack.hpp
index 148b19c98b..5253e3b153 100644
--- a/boost/asio/detail/call_stack.hpp
+++ b/boost/asio/detail/call_stack.hpp
@@ -2,7 +2,7 @@
// detail/call_stack.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/chrono_time_traits.hpp b/boost/asio/detail/chrono_time_traits.hpp
index f6bfed628c..421163a154 100644
--- a/boost/asio/detail/chrono_time_traits.hpp
+++ b/boost/asio/detail/chrono_time_traits.hpp
@@ -2,7 +2,7 @@
// detail/chrono_time_traits.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/completion_handler.hpp b/boost/asio/detail/completion_handler.hpp
index 3cfb1662f2..6333dce569 100644
--- a/boost/asio/detail/completion_handler.hpp
+++ b/boost/asio/detail/completion_handler.hpp
@@ -2,7 +2,7 @@
// detail/completion_handler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/config.hpp b/boost/asio/detail/config.hpp
index 319f94fe38..baeb86d78e 100644
--- a/boost/asio/detail/config.hpp
+++ b/boost/asio/detail/config.hpp
@@ -2,7 +2,7 @@
// detail/config.hpp
// ~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -435,6 +435,30 @@
# endif // !defined(BOOST_ASIO_DISABLE_STD_TYPE_TRAITS)
#endif // !defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS)
+// Standard library support for the C++11 allocator additions.
+#if !defined(BOOST_ASIO_HAS_CXX11_ALLOCATORS)
+# if !defined(BOOST_ASIO_DISABLE_CXX11_ALLOCATORS)
+# if defined(__clang__)
+# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX)
+# define BOOST_ASIO_HAS_CXX11_ALLOCATORS 1
+# elif (__cplusplus >= 201103)
+# define BOOST_ASIO_HAS_CXX11_ALLOCATORS 1
+# endif // (__cplusplus >= 201103)
+# elif defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_HAS_CXX11_ALLOCATORS 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1700)
+# define BOOST_ASIO_HAS_CXX11_ALLOCATORS 1
+# endif // (_MSC_VER >= 1700)
+# endif // defined(BOOST_ASIO_MSVC)
+# endif // !defined(BOOST_ASIO_DISABLE_CXX11_ALLOCATORS)
+#endif // !defined(BOOST_ASIO_HAS_CXX11_ALLOCATORS)
+
// Standard library support for the cstdint header.
#if !defined(BOOST_ASIO_HAS_CSTDINT)
# if !defined(BOOST_ASIO_DISABLE_CSTDINT)
@@ -993,4 +1017,34 @@
// || (defined(__MACH__) && defined(__APPLE__))
#endif // !defined(BOOST_ASIO_DISABLE_SSIZE_T)
+// Newer gcc, clang need special treatment to suppress unused typedef warnings.
+#if defined(__clang__)
+# if defined(__apple_build_version__)
+# if (__clang_major__ >= 7)
+# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
+# endif // (__clang_major__ >= 7)
+# elif ((__clang_major__ == 3) && (__clang_minor__ >= 6)) \
+ || (__clang_major__ > 3)
+# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
+# endif // ((__clang_major__ == 3) && (__clang_minor__ >= 6))
+ // || (__clang_major__ > 3)
+#elif defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
+# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
+#endif // defined(__GNUC__)
+#if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
+# define BOOST_ASIO_UNUSED_TYPEDEF
+#endif // !defined(BOOST_ASIO_UNUSED_TYPEDEF)
+
+// Some versions of gcc generate spurious warnings about unused variables.
+#if defined(__GNUC__)
+# if (__GNUC__ >= 4)
+# define BOOST_ASIO_UNUSED_VARIABLE __attribute__((__unused__))
+# endif // (__GNUC__ >= 4)
+#endif // defined(__GNUC__)
+#if !defined(BOOST_ASIO_UNUSED_VARIABLE)
+# define BOOST_ASIO_UNUSED_VARIABLE
+#endif // !defined(BOOST_ASIO_UNUSED_VARIABLE)
+
#endif // BOOST_ASIO_DETAIL_CONFIG_HPP
diff --git a/boost/asio/detail/consuming_buffers.hpp b/boost/asio/detail/consuming_buffers.hpp
index 8d7fc16c70..f0978b54d3 100644
--- a/boost/asio/detail/consuming_buffers.hpp
+++ b/boost/asio/detail/consuming_buffers.hpp
@@ -2,7 +2,7 @@
// detail/consuming_buffers.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/cstdint.hpp b/boost/asio/detail/cstdint.hpp
index 262d3a93c0..a1be0dced0 100644
--- a/boost/asio/detail/cstdint.hpp
+++ b/boost/asio/detail/cstdint.hpp
@@ -2,7 +2,7 @@
// detail/cstdint.hpp
// ~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/date_time_fwd.hpp b/boost/asio/detail/date_time_fwd.hpp
index c8756837fe..33191bfa71 100644
--- a/boost/asio/detail/date_time_fwd.hpp
+++ b/boost/asio/detail/date_time_fwd.hpp
@@ -2,7 +2,7 @@
// detail/date_time_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/deadline_timer_service.hpp b/boost/asio/detail/deadline_timer_service.hpp
index df22ec42b4..bbd5358425 100644
--- a/boost/asio/detail/deadline_timer_service.hpp
+++ b/boost/asio/detail/deadline_timer_service.hpp
@@ -2,7 +2,7 @@
// detail/deadline_timer_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/dependent_type.hpp b/boost/asio/detail/dependent_type.hpp
index 1a03a82820..138d0cc3d4 100644
--- a/boost/asio/detail/dependent_type.hpp
+++ b/boost/asio/detail/dependent_type.hpp
@@ -2,7 +2,7 @@
// detail/dependent_type.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/descriptor_ops.hpp b/boost/asio/detail/descriptor_ops.hpp
index d5a6319d2f..62100392da 100644
--- a/boost/asio/detail/descriptor_ops.hpp
+++ b/boost/asio/detail/descriptor_ops.hpp
@@ -2,7 +2,7 @@
// detail/descriptor_ops.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/descriptor_read_op.hpp b/boost/asio/detail/descriptor_read_op.hpp
index 2fc643db5e..ddbdf7d3e5 100644
--- a/boost/asio/detail/descriptor_read_op.hpp
+++ b/boost/asio/detail/descriptor_read_op.hpp
@@ -2,7 +2,7 @@
// detail/descriptor_read_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/descriptor_write_op.hpp b/boost/asio/detail/descriptor_write_op.hpp
index 6ca79a6f16..f635feb122 100644
--- a/boost/asio/detail/descriptor_write_op.hpp
+++ b/boost/asio/detail/descriptor_write_op.hpp
@@ -2,7 +2,7 @@
// detail/descriptor_write_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/dev_poll_reactor.hpp b/boost/asio/detail/dev_poll_reactor.hpp
index e18a44a24c..db6f3d1b8f 100644
--- a/boost/asio/detail/dev_poll_reactor.hpp
+++ b/boost/asio/detail/dev_poll_reactor.hpp
@@ -2,7 +2,7 @@
// detail/dev_poll_reactor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/epoll_reactor.hpp b/boost/asio/detail/epoll_reactor.hpp
index fe82481c65..64c5b2704c 100644
--- a/boost/asio/detail/epoll_reactor.hpp
+++ b/boost/asio/detail/epoll_reactor.hpp
@@ -2,7 +2,7 @@
// detail/epoll_reactor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/event.hpp b/boost/asio/detail/event.hpp
index a6616b11a1..45367bb257 100644
--- a/boost/asio/detail/event.hpp
+++ b/boost/asio/detail/event.hpp
@@ -2,7 +2,7 @@
// detail/event.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/eventfd_select_interrupter.hpp b/boost/asio/detail/eventfd_select_interrupter.hpp
index 0b1fcabdc2..c5b0b39206 100644
--- a/boost/asio/detail/eventfd_select_interrupter.hpp
+++ b/boost/asio/detail/eventfd_select_interrupter.hpp
@@ -2,7 +2,7 @@
// detail/eventfd_select_interrupter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/fd_set_adapter.hpp b/boost/asio/detail/fd_set_adapter.hpp
index 38464dc6dc..6916db5f25 100644
--- a/boost/asio/detail/fd_set_adapter.hpp
+++ b/boost/asio/detail/fd_set_adapter.hpp
@@ -2,7 +2,7 @@
// detail/fd_set_adapter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/fenced_block.hpp b/boost/asio/detail/fenced_block.hpp
index ad8667238e..628ca75f1c 100644
--- a/boost/asio/detail/fenced_block.hpp
+++ b/boost/asio/detail/fenced_block.hpp
@@ -2,7 +2,7 @@
// detail/fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -20,6 +20,8 @@
#if !defined(BOOST_ASIO_HAS_THREADS) \
|| defined(BOOST_ASIO_DISABLE_FENCED_BLOCK)
# include <boost/asio/detail/null_fenced_block.hpp>
+#elif defined(BOOST_ASIO_HAS_STD_ATOMIC)
+# include <boost/asio/detail/std_fenced_block.hpp>
#elif defined(__MACH__) && defined(__APPLE__)
# include <boost/asio/detail/macos_fenced_block.hpp>
#elif defined(__sun)
@@ -49,6 +51,8 @@ namespace detail {
#if !defined(BOOST_ASIO_HAS_THREADS) \
|| defined(BOOST_ASIO_DISABLE_FENCED_BLOCK)
typedef null_fenced_block fenced_block;
+#elif defined(BOOST_ASIO_HAS_STD_ATOMIC)
+typedef std_fenced_block fenced_block;
#elif defined(__MACH__) && defined(__APPLE__)
typedef macos_fenced_block fenced_block;
#elif defined(__sun)
diff --git a/boost/asio/detail/function.hpp b/boost/asio/detail/function.hpp
index 475efcb49a..db26144c5f 100644
--- a/boost/asio/detail/function.hpp
+++ b/boost/asio/detail/function.hpp
@@ -2,7 +2,7 @@
// detail/function.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/gcc_arm_fenced_block.hpp b/boost/asio/detail/gcc_arm_fenced_block.hpp
index 2f6cae4091..b4805c35cd 100644
--- a/boost/asio/detail/gcc_arm_fenced_block.hpp
+++ b/boost/asio/detail/gcc_arm_fenced_block.hpp
@@ -2,7 +2,7 @@
// detail/gcc_arm_fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/gcc_hppa_fenced_block.hpp b/boost/asio/detail/gcc_hppa_fenced_block.hpp
index b31e48bbf8..b9aa9e2ca4 100644
--- a/boost/asio/detail/gcc_hppa_fenced_block.hpp
+++ b/boost/asio/detail/gcc_hppa_fenced_block.hpp
@@ -2,7 +2,7 @@
// detail/gcc_hppa_fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/gcc_sync_fenced_block.hpp b/boost/asio/detail/gcc_sync_fenced_block.hpp
index 9db9f6413a..e8e6c54643 100644
--- a/boost/asio/detail/gcc_sync_fenced_block.hpp
+++ b/boost/asio/detail/gcc_sync_fenced_block.hpp
@@ -2,7 +2,7 @@
// detail/gcc_sync_fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/gcc_x86_fenced_block.hpp b/boost/asio/detail/gcc_x86_fenced_block.hpp
index 07354f6fb8..fe0ce8a316 100644
--- a/boost/asio/detail/gcc_x86_fenced_block.hpp
+++ b/boost/asio/detail/gcc_x86_fenced_block.hpp
@@ -2,7 +2,7 @@
// detail/gcc_x86_fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/handler_alloc_helpers.hpp b/boost/asio/detail/handler_alloc_helpers.hpp
index 16b7e268cd..a03cb41976 100644
--- a/boost/asio/detail/handler_alloc_helpers.hpp
+++ b/boost/asio/detail/handler_alloc_helpers.hpp
@@ -2,7 +2,7 @@
// detail/handler_alloc_helpers.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/handler_cont_helpers.hpp b/boost/asio/detail/handler_cont_helpers.hpp
index 90ae8a0f67..9a361a9ca4 100644
--- a/boost/asio/detail/handler_cont_helpers.hpp
+++ b/boost/asio/detail/handler_cont_helpers.hpp
@@ -2,7 +2,7 @@
// detail/handler_cont_helpers.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/handler_invoke_helpers.hpp b/boost/asio/detail/handler_invoke_helpers.hpp
index f5447abc1e..43f74f3272 100644
--- a/boost/asio/detail/handler_invoke_helpers.hpp
+++ b/boost/asio/detail/handler_invoke_helpers.hpp
@@ -2,7 +2,7 @@
// detail/handler_invoke_helpers.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/handler_tracking.hpp b/boost/asio/detail/handler_tracking.hpp
index 5f935f83e7..fd69bdd5b6 100644
--- a/boost/asio/detail/handler_tracking.hpp
+++ b/boost/asio/detail/handler_tracking.hpp
@@ -2,7 +2,7 @@
// detail/handler_tracking.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/handler_type_requirements.hpp b/boost/asio/detail/handler_type_requirements.hpp
index eb1908aa82..bc2fbce0ce 100644
--- a/boost/asio/detail/handler_type_requirements.hpp
+++ b/boost/asio/detail/handler_type_requirements.hpp
@@ -2,7 +2,7 @@
// detail/handler_type_requirements.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -53,26 +53,6 @@
# include <boost/asio/handler_type.hpp>
#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
-// Newer gcc, clang need special treatment to suppress unused typedef warnings.
-#if defined(__clang__)
-# if defined(__apple_build_version__)
-# if (__clang_major__ >= 7)
-# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
-# endif // (__clang_major__ >= 7)
-# elif ((__clang_major__ == 3) && (__clang_minor__ >= 6)) \
- || (__clang_major__ > 3)
-# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
-# endif // ((__clang_major__ == 3) && (__clang_minor__ >= 6))
- // || (__clang_major__ > 3)
-#elif defined(__GNUC__)
-# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
-# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
-# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
-#endif // defined(__GNUC__)
-#if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
-# define BOOST_ASIO_UNUSED_TYPEDEF
-#endif // !defined(BOOST_ASIO_UNUSED_TYPEDEF)
-
namespace boost {
namespace asio {
namespace detail {
diff --git a/boost/asio/detail/hash_map.hpp b/boost/asio/detail/hash_map.hpp
index da59857ce7..0c3b53bc39 100644
--- a/boost/asio/detail/hash_map.hpp
+++ b/boost/asio/detail/hash_map.hpp
@@ -2,7 +2,7 @@
// detail/hash_map.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -244,15 +244,15 @@ private:
{
if (num_buckets == num_buckets_)
return;
- num_buckets_ = num_buckets;
- BOOST_ASIO_ASSERT(num_buckets_ != 0);
+ BOOST_ASIO_ASSERT(num_buckets != 0);
iterator end_iter = values_.end();
// Update number of buckets and initialise all buckets to empty.
- bucket_type* tmp = new bucket_type[num_buckets_];
+ bucket_type* tmp = new bucket_type[num_buckets];
delete[] buckets_;
buckets_ = tmp;
+ num_buckets_ = num_buckets;
for (std::size_t i = 0; i < num_buckets_; ++i)
buckets_[i].first = buckets_[i].last = end_iter;
diff --git a/boost/asio/detail/impl/buffer_sequence_adapter.ipp b/boost/asio/detail/impl/buffer_sequence_adapter.ipp
index b53258293b..f471863e1a 100644
--- a/boost/asio/detail/impl/buffer_sequence_adapter.ipp
+++ b/boost/asio/detail/impl/buffer_sequence_adapter.ipp
@@ -2,7 +2,7 @@
// detail/impl/buffer_sequence_adapter.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/descriptor_ops.ipp b/boost/asio/detail/impl/descriptor_ops.ipp
index 0984b4b5c6..00f6b4796e 100644
--- a/boost/asio/detail/impl/descriptor_ops.ipp
+++ b/boost/asio/detail/impl/descriptor_ops.ipp
@@ -2,7 +2,7 @@
// detail/impl/descriptor_ops.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/dev_poll_reactor.hpp b/boost/asio/detail/impl/dev_poll_reactor.hpp
index 3e19406ba8..623346edd5 100644
--- a/boost/asio/detail/impl/dev_poll_reactor.hpp
+++ b/boost/asio/detail/impl/dev_poll_reactor.hpp
@@ -2,7 +2,7 @@
// detail/impl/dev_poll_reactor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/dev_poll_reactor.ipp b/boost/asio/detail/impl/dev_poll_reactor.ipp
index 521dc0b8da..efe2ba7086 100644
--- a/boost/asio/detail/impl/dev_poll_reactor.ipp
+++ b/boost/asio/detail/impl/dev_poll_reactor.ipp
@@ -2,7 +2,7 @@
// detail/impl/dev_poll_reactor.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/epoll_reactor.hpp b/boost/asio/detail/impl/epoll_reactor.hpp
index c579da59e6..ea5c6bfc69 100644
--- a/boost/asio/detail/impl/epoll_reactor.hpp
+++ b/boost/asio/detail/impl/epoll_reactor.hpp
@@ -2,7 +2,7 @@
// detail/impl/epoll_reactor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/epoll_reactor.ipp b/boost/asio/detail/impl/epoll_reactor.ipp
index 25eb005b32..610ce31ce5 100644
--- a/boost/asio/detail/impl/epoll_reactor.ipp
+++ b/boost/asio/detail/impl/epoll_reactor.ipp
@@ -2,7 +2,7 @@
// detail/impl/epoll_reactor.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -164,7 +164,18 @@ int epoll_reactor::register_descriptor(socket_type descriptor,
ev.data.ptr = descriptor_data;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
if (result != 0)
+ {
+ if (errno == EPERM)
+ {
+ // This file descriptor type is not supported by epoll. However, if it is
+ // a regular file then operations on it will not block. We will allow
+ // this descriptor to be used and fail later if an operation on it would
+ // otherwise require a trip through the reactor.
+ descriptor_data->registered_events_ = 0;
+ return 0;
+ }
return errno;
+ }
return 0;
}
@@ -235,6 +246,13 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
return;
}
+ if (descriptor_data->registered_events_ == 0)
+ {
+ op->ec_ = boost::asio::error::operation_not_supported;
+ io_service_.post_immediate_completion(op, is_continuation);
+ return;
+ }
+
if (op_type == write_op)
{
if ((descriptor_data->registered_events_ & EPOLLOUT) == 0)
@@ -256,6 +274,12 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
}
}
}
+ else if (descriptor_data->registered_events_ == 0)
+ {
+ op->ec_ = boost::asio::error::operation_not_supported;
+ io_service_.post_immediate_completion(op, is_continuation);
+ return;
+ }
else
{
if (op_type == write_op)
@@ -313,7 +337,7 @@ void epoll_reactor::deregister_descriptor(socket_type descriptor,
// The descriptor will be automatically removed from the epoll set when
// it is closed.
}
- else
+ else if (descriptor_data->registered_events_ != 0)
{
epoll_event ev = { 0, { 0 } };
epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
diff --git a/boost/asio/detail/impl/eventfd_select_interrupter.ipp b/boost/asio/detail/impl/eventfd_select_interrupter.ipp
index e245014a82..2ce1f6d674 100644
--- a/boost/asio/detail/impl/eventfd_select_interrupter.ipp
+++ b/boost/asio/detail/impl/eventfd_select_interrupter.ipp
@@ -2,7 +2,7 @@
// detail/impl/eventfd_select_interrupter.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/impl/handler_tracking.ipp b/boost/asio/detail/impl/handler_tracking.ipp
index 88cd1e9a33..259b5ab62b 100644
--- a/boost/asio/detail/impl/handler_tracking.ipp
+++ b/boost/asio/detail/impl/handler_tracking.ipp
@@ -2,7 +2,7 @@
// detail/impl/handler_tracking.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/kqueue_reactor.hpp b/boost/asio/detail/impl/kqueue_reactor.hpp
index 3025d559a4..93cbca26a2 100644
--- a/boost/asio/detail/impl/kqueue_reactor.hpp
+++ b/boost/asio/detail/impl/kqueue_reactor.hpp
@@ -2,7 +2,7 @@
// detail/impl/kqueue_reactor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/impl/kqueue_reactor.ipp b/boost/asio/detail/impl/kqueue_reactor.ipp
index 8aecd9b29b..b4a7a10b71 100644
--- a/boost/asio/detail/impl/kqueue_reactor.ipp
+++ b/boost/asio/detail/impl/kqueue_reactor.ipp
@@ -2,7 +2,7 @@
// detail/impl/kqueue_reactor.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/impl/pipe_select_interrupter.ipp b/boost/asio/detail/impl/pipe_select_interrupter.ipp
index 65eb233061..4f8923fa36 100644
--- a/boost/asio/detail/impl/pipe_select_interrupter.ipp
+++ b/boost/asio/detail/impl/pipe_select_interrupter.ipp
@@ -2,7 +2,7 @@
// detail/impl/pipe_select_interrupter.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/posix_event.ipp b/boost/asio/detail/impl/posix_event.ipp
index 62368c1f15..3b465ca3cd 100644
--- a/boost/asio/detail/impl/posix_event.ipp
+++ b/boost/asio/detail/impl/posix_event.ipp
@@ -2,7 +2,7 @@
// detail/impl/posix_event.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/posix_mutex.ipp b/boost/asio/detail/impl/posix_mutex.ipp
index bb96260d14..7153023ad3 100644
--- a/boost/asio/detail/impl/posix_mutex.ipp
+++ b/boost/asio/detail/impl/posix_mutex.ipp
@@ -2,7 +2,7 @@
// detail/impl/posix_mutex.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/posix_thread.ipp b/boost/asio/detail/impl/posix_thread.ipp
index c85c2ec82d..66cb18da33 100644
--- a/boost/asio/detail/impl/posix_thread.ipp
+++ b/boost/asio/detail/impl/posix_thread.ipp
@@ -2,7 +2,7 @@
// detail/impl/posix_thread.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/posix_tss_ptr.ipp b/boost/asio/detail/impl/posix_tss_ptr.ipp
index 143600383e..21b522c1da 100644
--- a/boost/asio/detail/impl/posix_tss_ptr.ipp
+++ b/boost/asio/detail/impl/posix_tss_ptr.ipp
@@ -2,7 +2,7 @@
// detail/impl/posix_tss_ptr.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/reactive_descriptor_service.ipp b/boost/asio/detail/impl/reactive_descriptor_service.ipp
index c7ad818080..56caec9fd3 100644
--- a/boost/asio/detail/impl/reactive_descriptor_service.ipp
+++ b/boost/asio/detail/impl/reactive_descriptor_service.ipp
@@ -2,7 +2,7 @@
// detail/impl/reactive_descriptor_service.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/reactive_serial_port_service.ipp b/boost/asio/detail/impl/reactive_serial_port_service.ipp
index 64172844d2..ffa8857ab6 100644
--- a/boost/asio/detail/impl/reactive_serial_port_service.ipp
+++ b/boost/asio/detail/impl/reactive_serial_port_service.ipp
@@ -2,7 +2,7 @@
// detail/impl/reactive_serial_port_service.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/impl/reactive_socket_service_base.ipp b/boost/asio/detail/impl/reactive_socket_service_base.ipp
index b15d085f59..21e77e9f93 100644
--- a/boost/asio/detail/impl/reactive_socket_service_base.ipp
+++ b/boost/asio/detail/impl/reactive_socket_service_base.ipp
@@ -2,7 +2,7 @@
// detail/reactive_socket_service_base.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/resolver_service_base.ipp b/boost/asio/detail/impl/resolver_service_base.ipp
index 3f4a410f10..4ef66cde15 100644
--- a/boost/asio/detail/impl/resolver_service_base.ipp
+++ b/boost/asio/detail/impl/resolver_service_base.ipp
@@ -2,7 +2,7 @@
// detail/impl/resolver_service_base.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/select_reactor.hpp b/boost/asio/detail/impl/select_reactor.hpp
index 2c89c64ce0..d3f28f5e61 100644
--- a/boost/asio/detail/impl/select_reactor.hpp
+++ b/boost/asio/detail/impl/select_reactor.hpp
@@ -2,7 +2,7 @@
// detail/impl/select_reactor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/select_reactor.ipp b/boost/asio/detail/impl/select_reactor.ipp
index df81051e3a..80686eaf97 100644
--- a/boost/asio/detail/impl/select_reactor.ipp
+++ b/boost/asio/detail/impl/select_reactor.ipp
@@ -2,7 +2,7 @@
// detail/impl/select_reactor.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/service_registry.hpp b/boost/asio/detail/impl/service_registry.hpp
index 89ecd24069..7ffdd029f7 100644
--- a/boost/asio/detail/impl/service_registry.hpp
+++ b/boost/asio/detail/impl/service_registry.hpp
@@ -2,7 +2,7 @@
// detail/impl/service_registry.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/service_registry.ipp b/boost/asio/detail/impl/service_registry.ipp
index 1023d289e3..25ac8eccc6 100644
--- a/boost/asio/detail/impl/service_registry.ipp
+++ b/boost/asio/detail/impl/service_registry.ipp
@@ -2,7 +2,7 @@
// detail/impl/service_registry.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/signal_set_service.ipp b/boost/asio/detail/impl/signal_set_service.ipp
index d05fa4c5dd..56313e0923 100644
--- a/boost/asio/detail/impl/signal_set_service.ipp
+++ b/boost/asio/detail/impl/signal_set_service.ipp
@@ -2,7 +2,7 @@
// detail/impl/signal_set_service.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/socket_ops.ipp b/boost/asio/detail/impl/socket_ops.ipp
index 1017aafb44..c9683f4a09 100644
--- a/boost/asio/detail/impl/socket_ops.ipp
+++ b/boost/asio/detail/impl/socket_ops.ipp
@@ -2,7 +2,7 @@
// detail/impl/socket_ops.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -3238,6 +3238,37 @@ boost::system::error_code getaddrinfo(const char* host,
return ec = translate_addrinfo_error(error);
#else
int error = ::getaddrinfo(host, service, &hints, result);
+#if defined(__MACH__) && defined(__APPLE__)
+ using namespace std; // For isdigit and atoi.
+ if (error == 0 && service && isdigit(static_cast<unsigned char>(service[0])))
+ {
+ u_short_type port = host_to_network_short(atoi(service));
+ for (addrinfo_type* ai = *result; ai; ai = ai->ai_next)
+ {
+ switch (ai->ai_family)
+ {
+ case BOOST_ASIO_OS_DEF(AF_INET):
+ {
+ sockaddr_in4_type* sinptr =
+ reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr);
+ if (sinptr->sin_port == 0)
+ sinptr->sin_port = port;
+ break;
+ }
+ case BOOST_ASIO_OS_DEF(AF_INET6):
+ {
+ sockaddr_in6_type* sin6ptr =
+ reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr);
+ if (sin6ptr->sin6_port == 0)
+ sin6ptr->sin6_port = port;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+#endif
return ec = translate_addrinfo_error(error);
#endif
}
diff --git a/boost/asio/detail/impl/socket_select_interrupter.ipp b/boost/asio/detail/impl/socket_select_interrupter.ipp
index 3ff6665289..409996c59e 100644
--- a/boost/asio/detail/impl/socket_select_interrupter.ipp
+++ b/boost/asio/detail/impl/socket_select_interrupter.ipp
@@ -2,7 +2,7 @@
// detail/impl/socket_select_interrupter.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/strand_service.hpp b/boost/asio/detail/impl/strand_service.hpp
index 45189a3710..4167f686d1 100644
--- a/boost/asio/detail/impl/strand_service.hpp
+++ b/boost/asio/detail/impl/strand_service.hpp
@@ -2,7 +2,7 @@
// detail/impl/strand_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/strand_service.ipp b/boost/asio/detail/impl/strand_service.ipp
index 7545559fff..54ecde2cc7 100644
--- a/boost/asio/detail/impl/strand_service.ipp
+++ b/boost/asio/detail/impl/strand_service.ipp
@@ -2,7 +2,7 @@
// detail/impl/strand_service.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/task_io_service.hpp b/boost/asio/detail/impl/task_io_service.hpp
index 5a19a01466..09b4ba6985 100644
--- a/boost/asio/detail/impl/task_io_service.hpp
+++ b/boost/asio/detail/impl/task_io_service.hpp
@@ -2,7 +2,7 @@
// detail/impl/task_io_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/task_io_service.ipp b/boost/asio/detail/impl/task_io_service.ipp
index 756e1889fe..bc83fd4757 100644
--- a/boost/asio/detail/impl/task_io_service.ipp
+++ b/boost/asio/detail/impl/task_io_service.ipp
@@ -2,7 +2,7 @@
// detail/impl/task_io_service.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/throw_error.ipp b/boost/asio/detail/impl/throw_error.ipp
index e95e071920..a1c31498c2 100644
--- a/boost/asio/detail/impl/throw_error.ipp
+++ b/boost/asio/detail/impl/throw_error.ipp
@@ -2,7 +2,7 @@
// detail/impl/throw_error.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/timer_queue_ptime.ipp b/boost/asio/detail/impl/timer_queue_ptime.ipp
index f665a5188e..0216d20ba5 100644
--- a/boost/asio/detail/impl/timer_queue_ptime.ipp
+++ b/boost/asio/detail/impl/timer_queue_ptime.ipp
@@ -2,7 +2,7 @@
// detail/impl/timer_queue_ptime.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/timer_queue_set.ipp b/boost/asio/detail/impl/timer_queue_set.ipp
index 81f7b62f68..25c845c11b 100644
--- a/boost/asio/detail/impl/timer_queue_set.ipp
+++ b/boost/asio/detail/impl/timer_queue_set.ipp
@@ -2,7 +2,7 @@
// detail/impl/timer_queue_set.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/win_event.ipp b/boost/asio/detail/impl/win_event.ipp
index 1280f00757..2519d3165d 100644
--- a/boost/asio/detail/impl/win_event.ipp
+++ b/boost/asio/detail/impl/win_event.ipp
@@ -2,7 +2,7 @@
// detail/win_event.ipp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/win_iocp_handle_service.ipp b/boost/asio/detail/impl/win_iocp_handle_service.ipp
index 09604439e2..ea513bc1dd 100644
--- a/boost/asio/detail/impl/win_iocp_handle_service.ipp
+++ b/boost/asio/detail/impl/win_iocp_handle_service.ipp
@@ -2,7 +2,7 @@
// detail/impl/win_iocp_handle_service.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/impl/win_iocp_io_service.hpp b/boost/asio/detail/impl/win_iocp_io_service.hpp
index 92344888bc..e3505cb852 100644
--- a/boost/asio/detail/impl/win_iocp_io_service.hpp
+++ b/boost/asio/detail/impl/win_iocp_io_service.hpp
@@ -2,7 +2,7 @@
// detail/impl/win_iocp_io_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/win_iocp_io_service.ipp b/boost/asio/detail/impl/win_iocp_io_service.ipp
index c26c3722b8..a5bfcbbdea 100644
--- a/boost/asio/detail/impl/win_iocp_io_service.ipp
+++ b/boost/asio/detail/impl/win_iocp_io_service.ipp
@@ -2,7 +2,7 @@
// detail/impl/win_iocp_io_service.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/win_iocp_serial_port_service.ipp b/boost/asio/detail/impl/win_iocp_serial_port_service.ipp
index 1c48465dd9..32ba34684b 100644
--- a/boost/asio/detail/impl/win_iocp_serial_port_service.ipp
+++ b/boost/asio/detail/impl/win_iocp_serial_port_service.ipp
@@ -2,7 +2,7 @@
// detail/impl/win_iocp_serial_port_service.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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 36fff850c2..22818f7e92 100644
--- a/boost/asio/detail/impl/win_iocp_socket_service_base.ipp
+++ b/boost/asio/detail/impl/win_iocp_socket_service_base.ipp
@@ -2,7 +2,7 @@
// detail/impl/win_iocp_socket_service_base.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/win_mutex.ipp b/boost/asio/detail/impl/win_mutex.ipp
index 6946fd1402..c4be08c5e9 100644
--- a/boost/asio/detail/impl/win_mutex.ipp
+++ b/boost/asio/detail/impl/win_mutex.ipp
@@ -2,7 +2,7 @@
// detail/impl/win_mutex.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -45,7 +45,8 @@ int win_mutex::do_init()
# if defined(UNDER_CE)
::InitializeCriticalSection(&crit_section_);
# elif defined(BOOST_ASIO_WINDOWS_APP)
- ::InitializeCriticalSectionEx(&crit_section_, 0x80000000, 0);
+ if (!::InitializeCriticalSectionEx(&crit_section_, 0, 0))
+ return ::GetLastError();
# else
if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))
return ::GetLastError();
@@ -58,7 +59,7 @@ int win_mutex::do_init()
::InitializeCriticalSection(&crit_section_);
# elif defined(BOOST_ASIO_WINDOWS_APP)
if (!::InitializeCriticalSectionEx(&crit_section_, 0, 0))
- return ::GetLastError();
+ return ::GetLastError();
# else
if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))
return ::GetLastError();
diff --git a/boost/asio/detail/impl/win_object_handle_service.ipp b/boost/asio/detail/impl/win_object_handle_service.ipp
index 16f7992f5c..a940161cba 100644
--- a/boost/asio/detail/impl/win_object_handle_service.ipp
+++ b/boost/asio/detail/impl/win_object_handle_service.ipp
@@ -2,7 +2,7 @@
// detail/impl/win_object_handle_service.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2011 Boris Schaeling (boris@highscore.de)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/impl/win_static_mutex.ipp b/boost/asio/detail/impl/win_static_mutex.ipp
index 18bb679eba..9b29da0d93 100644
--- a/boost/asio/detail/impl/win_static_mutex.ipp
+++ b/boost/asio/detail/impl/win_static_mutex.ipp
@@ -2,7 +2,7 @@
// detail/impl/win_static_mutex.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/win_thread.ipp b/boost/asio/detail/impl/win_thread.ipp
index 95689df9e5..e2d9384007 100644
--- a/boost/asio/detail/impl/win_thread.ipp
+++ b/boost/asio/detail/impl/win_thread.ipp
@@ -2,7 +2,7 @@
// detail/impl/win_thread.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/win_tss_ptr.ipp b/boost/asio/detail/impl/win_tss_ptr.ipp
index 0f4312c3e3..3390066695 100644
--- a/boost/asio/detail/impl/win_tss_ptr.ipp
+++ b/boost/asio/detail/impl/win_tss_ptr.ipp
@@ -2,7 +2,7 @@
// detail/impl/win_tss_ptr.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/winrt_ssocket_service_base.ipp b/boost/asio/detail/impl/winrt_ssocket_service_base.ipp
index e1ba90e8e4..f5990a97ad 100644
--- a/boost/asio/detail/impl/winrt_ssocket_service_base.ipp
+++ b/boost/asio/detail/impl/winrt_ssocket_service_base.ipp
@@ -2,7 +2,7 @@
// detail/impl/winrt_ssocket_service_base.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/winrt_timer_scheduler.hpp b/boost/asio/detail/impl/winrt_timer_scheduler.hpp
index bcc71733ba..8d93e57962 100644
--- a/boost/asio/detail/impl/winrt_timer_scheduler.hpp
+++ b/boost/asio/detail/impl/winrt_timer_scheduler.hpp
@@ -2,7 +2,7 @@
// detail/impl/winrt_timer_scheduler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/winrt_timer_scheduler.ipp b/boost/asio/detail/impl/winrt_timer_scheduler.ipp
index 07d24efa60..914849d822 100644
--- a/boost/asio/detail/impl/winrt_timer_scheduler.ipp
+++ b/boost/asio/detail/impl/winrt_timer_scheduler.ipp
@@ -2,7 +2,7 @@
// detail/impl/winrt_timer_scheduler.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/impl/winsock_init.ipp b/boost/asio/detail/impl/winsock_init.ipp
index 4ad204174d..57ef612547 100644
--- a/boost/asio/detail/impl/winsock_init.ipp
+++ b/boost/asio/detail/impl/winsock_init.ipp
@@ -2,7 +2,7 @@
// detail/impl/winsock_init.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/io_control.hpp b/boost/asio/detail/io_control.hpp
index 9c4a54bb2b..6c7527d1cf 100644
--- a/boost/asio/detail/io_control.hpp
+++ b/boost/asio/detail/io_control.hpp
@@ -2,7 +2,7 @@
// detail/io_control.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/keyword_tss_ptr.hpp b/boost/asio/detail/keyword_tss_ptr.hpp
index 26cb12c106..8a93adea1e 100644
--- a/boost/asio/detail/keyword_tss_ptr.hpp
+++ b/boost/asio/detail/keyword_tss_ptr.hpp
@@ -2,7 +2,7 @@
// detail/keyword_tss_ptr.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/kqueue_reactor.hpp b/boost/asio/detail/kqueue_reactor.hpp
index 8ed8f78634..6aba2b264f 100644
--- a/boost/asio/detail/kqueue_reactor.hpp
+++ b/boost/asio/detail/kqueue_reactor.hpp
@@ -2,7 +2,7 @@
// detail/kqueue_reactor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/local_free_on_block_exit.hpp b/boost/asio/detail/local_free_on_block_exit.hpp
index e3a59bb754..a51221676f 100644
--- a/boost/asio/detail/local_free_on_block_exit.hpp
+++ b/boost/asio/detail/local_free_on_block_exit.hpp
@@ -2,7 +2,7 @@
// detail/local_free_on_block_exit.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/macos_fenced_block.hpp b/boost/asio/detail/macos_fenced_block.hpp
index 4a98543c08..5ab7f91c5e 100644
--- a/boost/asio/detail/macos_fenced_block.hpp
+++ b/boost/asio/detail/macos_fenced_block.hpp
@@ -2,7 +2,7 @@
// detail/macos_fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/memory.hpp b/boost/asio/detail/memory.hpp
new file mode 100644
index 0000000000..479b57a3d1
--- /dev/null
+++ b/boost/asio/detail/memory.hpp
@@ -0,0 +1,31 @@
+//
+// detail/memory.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_MEMORY_HPP
+#define BOOST_ASIO_DETAIL_MEMORY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <memory>
+
+#if defined(BOOST_ASIO_HAS_CXX11_ALLOCATORS)
+# define BOOST_ASIO_REBIND_ALLOC(alloc, t) \
+ typename std::allocator_traits<alloc>::template rebind_alloc<t>
+ /**/
+#else // defined(BOOST_ASIO_HAS_CXX11_ALLOCATORS)
+# define BOOST_ASIO_REBIND_ALLOC(alloc, t) \
+ typename alloc::template rebind<t>::other
+ /**/
+#endif // defined(BOOST_ASIO_HAS_CXX11_ALLOCATORS)
+
+#endif // BOOST_ASIO_DETAIL_MEMORY_HPP
diff --git a/boost/asio/detail/mutex.hpp b/boost/asio/detail/mutex.hpp
index 81bada1f41..7c6917d83f 100644
--- a/boost/asio/detail/mutex.hpp
+++ b/boost/asio/detail/mutex.hpp
@@ -2,7 +2,7 @@
// detail/mutex.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/noncopyable.hpp b/boost/asio/detail/noncopyable.hpp
index fd35836efc..5f946c3f78 100644
--- a/boost/asio/detail/noncopyable.hpp
+++ b/boost/asio/detail/noncopyable.hpp
@@ -2,7 +2,7 @@
// detail/noncopyable.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/null_event.hpp b/boost/asio/detail/null_event.hpp
index 62a86566c2..28ba5ede55 100644
--- a/boost/asio/detail/null_event.hpp
+++ b/boost/asio/detail/null_event.hpp
@@ -2,7 +2,7 @@
// detail/null_event.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/null_fenced_block.hpp b/boost/asio/detail/null_fenced_block.hpp
index 237874fc12..27029b9e31 100644
--- a/boost/asio/detail/null_fenced_block.hpp
+++ b/boost/asio/detail/null_fenced_block.hpp
@@ -2,7 +2,7 @@
// detail/null_fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/null_mutex.hpp b/boost/asio/detail/null_mutex.hpp
index 82a69d38ec..b3f032b72d 100644
--- a/boost/asio/detail/null_mutex.hpp
+++ b/boost/asio/detail/null_mutex.hpp
@@ -2,7 +2,7 @@
// detail/null_mutex.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/null_reactor.hpp b/boost/asio/detail/null_reactor.hpp
index dee00d0332..2cfce63a4c 100644
--- a/boost/asio/detail/null_reactor.hpp
+++ b/boost/asio/detail/null_reactor.hpp
@@ -2,7 +2,7 @@
// detail/null_reactor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/null_signal_blocker.hpp b/boost/asio/detail/null_signal_blocker.hpp
index 8e73e78e03..4c00ec80c3 100644
--- a/boost/asio/detail/null_signal_blocker.hpp
+++ b/boost/asio/detail/null_signal_blocker.hpp
@@ -2,7 +2,7 @@
// detail/null_signal_blocker.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/null_socket_service.hpp b/boost/asio/detail/null_socket_service.hpp
index 9dbccba535..bf06ebb545 100644
--- a/boost/asio/detail/null_socket_service.hpp
+++ b/boost/asio/detail/null_socket_service.hpp
@@ -2,7 +2,7 @@
// detail/null_socket_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -79,6 +79,7 @@ public:
// Move-construct a new socket implementation from another protocol type.
template <typename Protocol1>
void converting_move_construct(implementation_type&,
+ null_socket_service<Protocol1>&,
typename null_socket_service<Protocol1>::implementation_type&)
{
}
diff --git a/boost/asio/detail/null_static_mutex.hpp b/boost/asio/detail/null_static_mutex.hpp
index 9945c6d19e..ba644719fc 100644
--- a/boost/asio/detail/null_static_mutex.hpp
+++ b/boost/asio/detail/null_static_mutex.hpp
@@ -2,7 +2,7 @@
// detail/null_static_mutex.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/null_thread.hpp b/boost/asio/detail/null_thread.hpp
index 54e79a9c81..5e9b458638 100644
--- a/boost/asio/detail/null_thread.hpp
+++ b/boost/asio/detail/null_thread.hpp
@@ -2,7 +2,7 @@
// detail/null_thread.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/null_tss_ptr.hpp b/boost/asio/detail/null_tss_ptr.hpp
index 70a3a1af1c..30306770f4 100644
--- a/boost/asio/detail/null_tss_ptr.hpp
+++ b/boost/asio/detail/null_tss_ptr.hpp
@@ -2,7 +2,7 @@
// detail/null_tss_ptr.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/object_pool.hpp b/boost/asio/detail/object_pool.hpp
index 9fd389d497..692efed09d 100644
--- a/boost/asio/detail/object_pool.hpp
+++ b/boost/asio/detail/object_pool.hpp
@@ -2,7 +2,7 @@
// detail/object_pool.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/old_win_sdk_compat.hpp b/boost/asio/detail/old_win_sdk_compat.hpp
index 85b98bb2ce..403ff75837 100644
--- a/boost/asio/detail/old_win_sdk_compat.hpp
+++ b/boost/asio/detail/old_win_sdk_compat.hpp
@@ -2,7 +2,7 @@
// detail/old_win_sdk_compat.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/op_queue.hpp b/boost/asio/detail/op_queue.hpp
index 13208357cc..9605248567 100644
--- a/boost/asio/detail/op_queue.hpp
+++ b/boost/asio/detail/op_queue.hpp
@@ -2,7 +2,7 @@
// detail/op_queue.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/operation.hpp b/boost/asio/detail/operation.hpp
index 44f5a0f812..a186a1f4d8 100644
--- a/boost/asio/detail/operation.hpp
+++ b/boost/asio/detail/operation.hpp
@@ -2,7 +2,7 @@
// detail/operation.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/pipe_select_interrupter.hpp b/boost/asio/detail/pipe_select_interrupter.hpp
index 977aa38a98..3a51baa78d 100644
--- a/boost/asio/detail/pipe_select_interrupter.hpp
+++ b/boost/asio/detail/pipe_select_interrupter.hpp
@@ -2,7 +2,7 @@
// detail/pipe_select_interrupter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/pop_options.hpp b/boost/asio/detail/pop_options.hpp
index c6ba5e2ae8..29213ede7b 100644
--- a/boost/asio/detail/pop_options.hpp
+++ b/boost/asio/detail/pop_options.hpp
@@ -2,7 +2,7 @@
// detail/pop_options.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/posix_event.hpp b/boost/asio/detail/posix_event.hpp
index 750ec82c8d..4eae96e2a8 100644
--- a/boost/asio/detail/posix_event.hpp
+++ b/boost/asio/detail/posix_event.hpp
@@ -2,7 +2,7 @@
// detail/posix_event.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/posix_fd_set_adapter.hpp b/boost/asio/detail/posix_fd_set_adapter.hpp
index 3808059eba..964f11ff88 100644
--- a/boost/asio/detail/posix_fd_set_adapter.hpp
+++ b/boost/asio/detail/posix_fd_set_adapter.hpp
@@ -2,7 +2,7 @@
// detail/posix_fd_set_adapter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/posix_mutex.hpp b/boost/asio/detail/posix_mutex.hpp
index 8683c71edb..3179281a8f 100644
--- a/boost/asio/detail/posix_mutex.hpp
+++ b/boost/asio/detail/posix_mutex.hpp
@@ -2,7 +2,7 @@
// detail/posix_mutex.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/posix_signal_blocker.hpp b/boost/asio/detail/posix_signal_blocker.hpp
index a9933ef9e0..b774727497 100644
--- a/boost/asio/detail/posix_signal_blocker.hpp
+++ b/boost/asio/detail/posix_signal_blocker.hpp
@@ -2,7 +2,7 @@
// detail/posix_signal_blocker.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/posix_static_mutex.hpp b/boost/asio/detail/posix_static_mutex.hpp
index 1b76651ea9..3895bfc60b 100644
--- a/boost/asio/detail/posix_static_mutex.hpp
+++ b/boost/asio/detail/posix_static_mutex.hpp
@@ -2,7 +2,7 @@
// detail/posix_static_mutex.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/posix_thread.hpp b/boost/asio/detail/posix_thread.hpp
index 4ef1e0ea69..ddf5ba46f3 100644
--- a/boost/asio/detail/posix_thread.hpp
+++ b/boost/asio/detail/posix_thread.hpp
@@ -2,7 +2,7 @@
// detail/posix_thread.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/posix_tss_ptr.hpp b/boost/asio/detail/posix_tss_ptr.hpp
index b765e52ca4..64b7d12021 100644
--- a/boost/asio/detail/posix_tss_ptr.hpp
+++ b/boost/asio/detail/posix_tss_ptr.hpp
@@ -2,7 +2,7 @@
// detail/posix_tss_ptr.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/push_options.hpp b/boost/asio/detail/push_options.hpp
index a24a267573..ae189c0519 100644
--- a/boost/asio/detail/push_options.hpp
+++ b/boost/asio/detail/push_options.hpp
@@ -2,7 +2,7 @@
// detail/push_options.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactive_descriptor_service.hpp b/boost/asio/detail/reactive_descriptor_service.hpp
index 88f82ae857..3d6d1e98c8 100644
--- a/boost/asio/detail/reactive_descriptor_service.hpp
+++ b/boost/asio/detail/reactive_descriptor_service.hpp
@@ -2,7 +2,7 @@
// detail/reactive_descriptor_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactive_null_buffers_op.hpp b/boost/asio/detail/reactive_null_buffers_op.hpp
index 6b1f47c854..4b1c7fedbf 100644
--- a/boost/asio/detail/reactive_null_buffers_op.hpp
+++ b/boost/asio/detail/reactive_null_buffers_op.hpp
@@ -2,7 +2,7 @@
// detail/reactive_null_buffers_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactive_serial_port_service.hpp b/boost/asio/detail/reactive_serial_port_service.hpp
index 898d432fe4..4976fbd08e 100644
--- a/boost/asio/detail/reactive_serial_port_service.hpp
+++ b/boost/asio/detail/reactive_serial_port_service.hpp
@@ -2,7 +2,7 @@
// detail/reactive_serial_port_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/reactive_socket_accept_op.hpp b/boost/asio/detail/reactive_socket_accept_op.hpp
index 63bc4c0beb..fec6bddb55 100644
--- a/boost/asio/detail/reactive_socket_accept_op.hpp
+++ b/boost/asio/detail/reactive_socket_accept_op.hpp
@@ -2,7 +2,7 @@
// detail/reactive_socket_accept_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactive_socket_connect_op.hpp b/boost/asio/detail/reactive_socket_connect_op.hpp
index 7a0afd01c3..809d63b7ae 100644
--- a/boost/asio/detail/reactive_socket_connect_op.hpp
+++ b/boost/asio/detail/reactive_socket_connect_op.hpp
@@ -2,7 +2,7 @@
// detail/reactive_socket_connect_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactive_socket_recv_op.hpp b/boost/asio/detail/reactive_socket_recv_op.hpp
index bf9fd5865f..751160c48f 100644
--- a/boost/asio/detail/reactive_socket_recv_op.hpp
+++ b/boost/asio/detail/reactive_socket_recv_op.hpp
@@ -2,7 +2,7 @@
// detail/reactive_socket_recv_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactive_socket_recvfrom_op.hpp b/boost/asio/detail/reactive_socket_recvfrom_op.hpp
index a2b50f8aaa..14829a0d75 100644
--- a/boost/asio/detail/reactive_socket_recvfrom_op.hpp
+++ b/boost/asio/detail/reactive_socket_recvfrom_op.hpp
@@ -2,7 +2,7 @@
// detail/reactive_socket_recvfrom_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactive_socket_recvmsg_op.hpp b/boost/asio/detail/reactive_socket_recvmsg_op.hpp
index 4c3672484c..fed5d01098 100644
--- a/boost/asio/detail/reactive_socket_recvmsg_op.hpp
+++ b/boost/asio/detail/reactive_socket_recvmsg_op.hpp
@@ -2,7 +2,7 @@
// detail/reactive_socket_recvmsg_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactive_socket_send_op.hpp b/boost/asio/detail/reactive_socket_send_op.hpp
index d9775db3e3..776117b6f7 100644
--- a/boost/asio/detail/reactive_socket_send_op.hpp
+++ b/boost/asio/detail/reactive_socket_send_op.hpp
@@ -2,7 +2,7 @@
// detail/reactive_socket_send_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactive_socket_sendto_op.hpp b/boost/asio/detail/reactive_socket_sendto_op.hpp
index 6e8595b669..134c767c86 100644
--- a/boost/asio/detail/reactive_socket_sendto_op.hpp
+++ b/boost/asio/detail/reactive_socket_sendto_op.hpp
@@ -2,7 +2,7 @@
// detail/reactive_socket_sendto_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactive_socket_service.hpp b/boost/asio/detail/reactive_socket_service.hpp
index bbb6ddba87..d5a6e08eab 100644
--- a/boost/asio/detail/reactive_socket_service.hpp
+++ b/boost/asio/detail/reactive_socket_service.hpp
@@ -2,7 +2,7 @@
// detail/reactive_socket_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -102,6 +102,7 @@ public:
// Move-construct a new socket implementation from another protocol type.
template <typename Protocol1>
void converting_move_construct(implementation_type& impl,
+ reactive_socket_service<Protocol1>&,
typename reactive_socket_service<
Protocol1>::implementation_type& other_impl)
{
diff --git a/boost/asio/detail/reactive_socket_service_base.hpp b/boost/asio/detail/reactive_socket_service_base.hpp
index 2a429e7aee..fb2aa5d028 100644
--- a/boost/asio/detail/reactive_socket_service_base.hpp
+++ b/boost/asio/detail/reactive_socket_service_base.hpp
@@ -2,7 +2,7 @@
// detail/reactive_socket_service_base.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactor.hpp b/boost/asio/detail/reactor.hpp
index 9314321baf..1a4ace8776 100644
--- a/boost/asio/detail/reactor.hpp
+++ b/boost/asio/detail/reactor.hpp
@@ -2,7 +2,7 @@
// detail/reactor.hpp
// ~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactor_fwd.hpp b/boost/asio/detail/reactor_fwd.hpp
index a9132e2b0f..6b2e49f5a4 100644
--- a/boost/asio/detail/reactor_fwd.hpp
+++ b/boost/asio/detail/reactor_fwd.hpp
@@ -2,7 +2,7 @@
// detail/reactor_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactor_op.hpp b/boost/asio/detail/reactor_op.hpp
index dd6c4ddabb..c5964dea37 100644
--- a/boost/asio/detail/reactor_op.hpp
+++ b/boost/asio/detail/reactor_op.hpp
@@ -2,7 +2,7 @@
// detail/reactor_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/reactor_op_queue.hpp b/boost/asio/detail/reactor_op_queue.hpp
index 379a4a2940..4be5c2e05e 100644
--- a/boost/asio/detail/reactor_op_queue.hpp
+++ b/boost/asio/detail/reactor_op_queue.hpp
@@ -2,7 +2,7 @@
// detail/reactor_op_queue.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/regex_fwd.hpp b/boost/asio/detail/regex_fwd.hpp
index a0aa6510c4..122d7b52e3 100644
--- a/boost/asio/detail/regex_fwd.hpp
+++ b/boost/asio/detail/regex_fwd.hpp
@@ -2,7 +2,7 @@
// detail/regex_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/resolve_endpoint_op.hpp b/boost/asio/detail/resolve_endpoint_op.hpp
index bc6828f9bb..0b7060ad6b 100644
--- a/boost/asio/detail/resolve_endpoint_op.hpp
+++ b/boost/asio/detail/resolve_endpoint_op.hpp
@@ -2,7 +2,7 @@
// detail/resolve_endpoint_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/resolve_op.hpp b/boost/asio/detail/resolve_op.hpp
index 3c5a43afce..435e27026f 100644
--- a/boost/asio/detail/resolve_op.hpp
+++ b/boost/asio/detail/resolve_op.hpp
@@ -2,7 +2,7 @@
// detail/resolve_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/resolver_service.hpp b/boost/asio/detail/resolver_service.hpp
index 3a43ff320f..f73742e9b0 100644
--- a/boost/asio/detail/resolver_service.hpp
+++ b/boost/asio/detail/resolver_service.hpp
@@ -2,7 +2,7 @@
// detail/resolver_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/resolver_service_base.hpp b/boost/asio/detail/resolver_service_base.hpp
index f47df9fe8d..1a4180c166 100644
--- a/boost/asio/detail/resolver_service_base.hpp
+++ b/boost/asio/detail/resolver_service_base.hpp
@@ -2,7 +2,7 @@
// detail/resolver_service_base.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/scoped_lock.hpp b/boost/asio/detail/scoped_lock.hpp
index ca8bf0698a..239dd6a940 100644
--- a/boost/asio/detail/scoped_lock.hpp
+++ b/boost/asio/detail/scoped_lock.hpp
@@ -2,7 +2,7 @@
// detail/scoped_lock.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/scoped_ptr.hpp b/boost/asio/detail/scoped_ptr.hpp
index 24c5b72647..fd471631e1 100644
--- a/boost/asio/detail/scoped_ptr.hpp
+++ b/boost/asio/detail/scoped_ptr.hpp
@@ -2,7 +2,7 @@
// detail/scoped_ptr.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/select_interrupter.hpp b/boost/asio/detail/select_interrupter.hpp
index 885014ae78..a6c27a72f9 100644
--- a/boost/asio/detail/select_interrupter.hpp
+++ b/boost/asio/detail/select_interrupter.hpp
@@ -2,7 +2,7 @@
// detail/select_interrupter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/select_reactor.hpp b/boost/asio/detail/select_reactor.hpp
index 48c944e405..69b04c82b5 100644
--- a/boost/asio/detail/select_reactor.hpp
+++ b/boost/asio/detail/select_reactor.hpp
@@ -2,7 +2,7 @@
// detail/select_reactor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/service_registry.hpp b/boost/asio/detail/service_registry.hpp
index 51d9f601dd..b5fa85bd01 100644
--- a/boost/asio/detail/service_registry.hpp
+++ b/boost/asio/detail/service_registry.hpp
@@ -2,7 +2,7 @@
// detail/service_registry.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/shared_ptr.hpp b/boost/asio/detail/shared_ptr.hpp
index f37dcc40cd..f26c645121 100644
--- a/boost/asio/detail/shared_ptr.hpp
+++ b/boost/asio/detail/shared_ptr.hpp
@@ -2,7 +2,7 @@
// detail/shared_ptr.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/signal_blocker.hpp b/boost/asio/detail/signal_blocker.hpp
index bfed3fcd8d..c4d14f607d 100644
--- a/boost/asio/detail/signal_blocker.hpp
+++ b/boost/asio/detail/signal_blocker.hpp
@@ -2,7 +2,7 @@
// detail/signal_blocker.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/signal_handler.hpp b/boost/asio/detail/signal_handler.hpp
index 00d9c9e992..edad41b8ee 100644
--- a/boost/asio/detail/signal_handler.hpp
+++ b/boost/asio/detail/signal_handler.hpp
@@ -2,7 +2,7 @@
// detail/signal_handler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/signal_init.hpp b/boost/asio/detail/signal_init.hpp
index 67eefe2e1f..5065d6d8d9 100644
--- a/boost/asio/detail/signal_init.hpp
+++ b/boost/asio/detail/signal_init.hpp
@@ -2,7 +2,7 @@
// detail/signal_init.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/signal_op.hpp b/boost/asio/detail/signal_op.hpp
index 5faab9813e..c8dfd52a0e 100644
--- a/boost/asio/detail/signal_op.hpp
+++ b/boost/asio/detail/signal_op.hpp
@@ -2,7 +2,7 @@
// detail/signal_op.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/signal_set_service.hpp b/boost/asio/detail/signal_set_service.hpp
index bfb2280186..a023ebb66f 100644
--- a/boost/asio/detail/signal_set_service.hpp
+++ b/boost/asio/detail/signal_set_service.hpp
@@ -2,7 +2,7 @@
// detail/signal_set_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/socket_holder.hpp b/boost/asio/detail/socket_holder.hpp
index 9e8389e767..8a3c8e8917 100644
--- a/boost/asio/detail/socket_holder.hpp
+++ b/boost/asio/detail/socket_holder.hpp
@@ -2,7 +2,7 @@
// detail/socket_holder.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/socket_ops.hpp b/boost/asio/detail/socket_ops.hpp
index cf213ecb74..136a3f01f7 100644
--- a/boost/asio/detail/socket_ops.hpp
+++ b/boost/asio/detail/socket_ops.hpp
@@ -2,7 +2,7 @@
// detail/socket_ops.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/socket_option.hpp b/boost/asio/detail/socket_option.hpp
index e3bc274469..2ca77badc8 100644
--- a/boost/asio/detail/socket_option.hpp
+++ b/boost/asio/detail/socket_option.hpp
@@ -2,7 +2,7 @@
// detail/socket_option.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/socket_select_interrupter.hpp b/boost/asio/detail/socket_select_interrupter.hpp
index 0dd5fc2e3f..82bcaba5f1 100644
--- a/boost/asio/detail/socket_select_interrupter.hpp
+++ b/boost/asio/detail/socket_select_interrupter.hpp
@@ -2,7 +2,7 @@
// detail/socket_select_interrupter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/socket_types.hpp b/boost/asio/detail/socket_types.hpp
index d0c255032d..8467118b54 100644
--- a/boost/asio/detail/socket_types.hpp
+++ b/boost/asio/detail/socket_types.hpp
@@ -2,7 +2,7 @@
// detail/socket_types.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -30,13 +30,13 @@
# define BOOST_ASIO_WSPIAPI_H_DEFINED
# endif // !defined(_WSPIAPI_H_)
# endif // defined(__BORLANDC__)
+# include <winsock2.h>
+# include <ws2tcpip.h>
# if defined(WINAPI_FAMILY)
# if ((WINAPI_FAMILY & WINAPI_PARTITION_DESKTOP) != 0)
# include <windows.h>
# endif // ((WINAPI_FAMILY & WINAPI_PARTITION_DESKTOP) != 0)
# endif // defined(WINAPI_FAMILY)
-# include <winsock2.h>
-# include <ws2tcpip.h>
# if !defined(BOOST_ASIO_WINDOWS_APP)
# include <mswsock.h>
# endif // !defined(BOOST_ASIO_WINDOWS_APP)
diff --git a/boost/asio/detail/solaris_fenced_block.hpp b/boost/asio/detail/solaris_fenced_block.hpp
index 28da41c3a2..2aef0229f1 100644
--- a/boost/asio/detail/solaris_fenced_block.hpp
+++ b/boost/asio/detail/solaris_fenced_block.hpp
@@ -2,7 +2,7 @@
// detail/solaris_fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/static_mutex.hpp b/boost/asio/detail/static_mutex.hpp
index 3625c41ffc..d4af68f1ca 100644
--- a/boost/asio/detail/static_mutex.hpp
+++ b/boost/asio/detail/static_mutex.hpp
@@ -2,7 +2,7 @@
// detail/static_mutex.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/std_event.hpp b/boost/asio/detail/std_event.hpp
index 1d28bf57aa..2add1f9f8c 100644
--- a/boost/asio/detail/std_event.hpp
+++ b/boost/asio/detail/std_event.hpp
@@ -2,7 +2,7 @@
// detail/std_event.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/std_fenced_block.hpp b/boost/asio/detail/std_fenced_block.hpp
new file mode 100644
index 0000000000..b3bd9d5931
--- /dev/null
+++ b/boost/asio/detail/std_fenced_block.hpp
@@ -0,0 +1,64 @@
+//
+// detail/std_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_STD_FENCED_BLOCK_HPP
+#define BOOST_ASIO_DETAIL_STD_FENCED_BLOCK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_STD_ATOMIC)
+
+#include <atomic>
+#include <boost/asio/detail/noncopyable.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class std_fenced_block
+ : private noncopyable
+{
+public:
+ enum half_t { half };
+ enum full_t { full };
+
+ // Constructor for a half fenced block.
+ explicit std_fenced_block(half_t)
+ {
+ }
+
+ // Constructor for a full fenced block.
+ explicit std_fenced_block(full_t)
+ {
+ std::atomic_thread_fence(std::memory_order_acquire);
+ }
+
+ // Destructor.
+ ~std_fenced_block()
+ {
+ std::atomic_thread_fence(std::memory_order_release);
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_HAS_STD_ATOMIC)
+
+#endif // BOOST_ASIO_DETAIL_STD_FENCED_BLOCK_HPP
diff --git a/boost/asio/detail/std_mutex.hpp b/boost/asio/detail/std_mutex.hpp
index 45ce252c6e..ac60e2337d 100644
--- a/boost/asio/detail/std_mutex.hpp
+++ b/boost/asio/detail/std_mutex.hpp
@@ -2,7 +2,7 @@
// detail/std_mutex.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/std_static_mutex.hpp b/boost/asio/detail/std_static_mutex.hpp
index a7c4274511..a2b2c6f83e 100644
--- a/boost/asio/detail/std_static_mutex.hpp
+++ b/boost/asio/detail/std_static_mutex.hpp
@@ -2,7 +2,7 @@
// detail/std_static_mutex.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/std_thread.hpp b/boost/asio/detail/std_thread.hpp
index 25dc64bc8d..cd2a61dac2 100644
--- a/boost/asio/detail/std_thread.hpp
+++ b/boost/asio/detail/std_thread.hpp
@@ -2,7 +2,7 @@
// detail/std_thread.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/strand_service.hpp b/boost/asio/detail/strand_service.hpp
index 4fe7ed4cb8..8a94e58e36 100644
--- a/boost/asio/detail/strand_service.hpp
+++ b/boost/asio/detail/strand_service.hpp
@@ -2,7 +2,7 @@
// detail/strand_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/task_io_service.hpp b/boost/asio/detail/task_io_service.hpp
index 933548ed20..5184ea5a58 100644
--- a/boost/asio/detail/task_io_service.hpp
+++ b/boost/asio/detail/task_io_service.hpp
@@ -2,7 +2,7 @@
// detail/task_io_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/task_io_service_operation.hpp b/boost/asio/detail/task_io_service_operation.hpp
index e63ca2d956..91bee25cb4 100644
--- a/boost/asio/detail/task_io_service_operation.hpp
+++ b/boost/asio/detail/task_io_service_operation.hpp
@@ -2,7 +2,7 @@
// detail/task_io_service_operation.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/task_io_service_thread_info.hpp b/boost/asio/detail/task_io_service_thread_info.hpp
index f0e9b62ee4..0af044c009 100644
--- a/boost/asio/detail/task_io_service_thread_info.hpp
+++ b/boost/asio/detail/task_io_service_thread_info.hpp
@@ -2,7 +2,7 @@
// detail/task_io_service_thread_info.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/thread.hpp b/boost/asio/detail/thread.hpp
index 05137375bf..f385fc85a1 100644
--- a/boost/asio/detail/thread.hpp
+++ b/boost/asio/detail/thread.hpp
@@ -2,7 +2,7 @@
// detail/thread.hpp
// ~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/thread_info_base.hpp b/boost/asio/detail/thread_info_base.hpp
index bd564e8540..3baa8ef39f 100644
--- a/boost/asio/detail/thread_info_base.hpp
+++ b/boost/asio/detail/thread_info_base.hpp
@@ -2,7 +2,7 @@
// detail/thread_info_base.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/throw_error.hpp b/boost/asio/detail/throw_error.hpp
index 0c3effea9c..6669f2e527 100644
--- a/boost/asio/detail/throw_error.hpp
+++ b/boost/asio/detail/throw_error.hpp
@@ -2,7 +2,7 @@
// detail/throw_error.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/throw_exception.hpp b/boost/asio/detail/throw_exception.hpp
index 18f7081267..9f0052ad42 100644
--- a/boost/asio/detail/throw_exception.hpp
+++ b/boost/asio/detail/throw_exception.hpp
@@ -2,7 +2,7 @@
// detail/throw_exception.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/timer_queue.hpp b/boost/asio/detail/timer_queue.hpp
index 8c8df3e1b5..cb848dfb3a 100644
--- a/boost/asio/detail/timer_queue.hpp
+++ b/boost/asio/detail/timer_queue.hpp
@@ -2,7 +2,7 @@
// detail/timer_queue.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/timer_queue_base.hpp b/boost/asio/detail/timer_queue_base.hpp
index f17119804a..33f005d456 100644
--- a/boost/asio/detail/timer_queue_base.hpp
+++ b/boost/asio/detail/timer_queue_base.hpp
@@ -2,7 +2,7 @@
// detail/timer_queue_base.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/timer_queue_ptime.hpp b/boost/asio/detail/timer_queue_ptime.hpp
index e1a7eff272..0693acca83 100644
--- a/boost/asio/detail/timer_queue_ptime.hpp
+++ b/boost/asio/detail/timer_queue_ptime.hpp
@@ -2,7 +2,7 @@
// detail/timer_queue_ptime.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/timer_queue_set.hpp b/boost/asio/detail/timer_queue_set.hpp
index 25d575a628..b044edd593 100644
--- a/boost/asio/detail/timer_queue_set.hpp
+++ b/boost/asio/detail/timer_queue_set.hpp
@@ -2,7 +2,7 @@
// detail/timer_queue_set.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/timer_scheduler.hpp b/boost/asio/detail/timer_scheduler.hpp
index 74a9c26b3f..49dc113d10 100644
--- a/boost/asio/detail/timer_scheduler.hpp
+++ b/boost/asio/detail/timer_scheduler.hpp
@@ -2,7 +2,7 @@
// detail/timer_scheduler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/timer_scheduler_fwd.hpp b/boost/asio/detail/timer_scheduler_fwd.hpp
index bd1710ec50..bf732a63d3 100644
--- a/boost/asio/detail/timer_scheduler_fwd.hpp
+++ b/boost/asio/detail/timer_scheduler_fwd.hpp
@@ -2,7 +2,7 @@
// detail/timer_scheduler_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/tss_ptr.hpp b/boost/asio/detail/tss_ptr.hpp
index 085a3cf64e..a3d41ca6bd 100644
--- a/boost/asio/detail/tss_ptr.hpp
+++ b/boost/asio/detail/tss_ptr.hpp
@@ -2,7 +2,7 @@
// detail/tss_ptr.hpp
// ~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/type_traits.hpp b/boost/asio/detail/type_traits.hpp
index 2d05563645..53a73a0eb1 100644
--- a/boost/asio/detail/type_traits.hpp
+++ b/boost/asio/detail/type_traits.hpp
@@ -2,7 +2,7 @@
// detail/type_traits.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/variadic_templates.hpp b/boost/asio/detail/variadic_templates.hpp
index bc6e2078fe..6d55bc7a7c 100644
--- a/boost/asio/detail/variadic_templates.hpp
+++ b/boost/asio/detail/variadic_templates.hpp
@@ -2,7 +2,7 @@
// detail/variadic_templates.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/wait_handler.hpp b/boost/asio/detail/wait_handler.hpp
index 016d9ad4fc..440dae1f18 100644
--- a/boost/asio/detail/wait_handler.hpp
+++ b/boost/asio/detail/wait_handler.hpp
@@ -2,7 +2,7 @@
// detail/wait_handler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/wait_op.hpp b/boost/asio/detail/wait_op.hpp
index 596c529c49..16835139b6 100644
--- a/boost/asio/detail/wait_op.hpp
+++ b/boost/asio/detail/wait_op.hpp
@@ -2,7 +2,7 @@
// detail/wait_op.hpp
// ~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/weak_ptr.hpp b/boost/asio/detail/weak_ptr.hpp
index 5a07ad179b..1870c0e0e8 100644
--- a/boost/asio/detail/weak_ptr.hpp
+++ b/boost/asio/detail/weak_ptr.hpp
@@ -2,7 +2,7 @@
// detail/weak_ptr.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_event.hpp b/boost/asio/detail/win_event.hpp
index 0efc31ee8b..7a7d54fac6 100644
--- a/boost/asio/detail/win_event.hpp
+++ b/boost/asio/detail/win_event.hpp
@@ -2,7 +2,7 @@
// detail/win_event.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_fd_set_adapter.hpp b/boost/asio/detail/win_fd_set_adapter.hpp
index bcbc39be6f..b8e1b31a09 100644
--- a/boost/asio/detail/win_fd_set_adapter.hpp
+++ b/boost/asio/detail/win_fd_set_adapter.hpp
@@ -2,7 +2,7 @@
// detail/win_fd_set_adapter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_fenced_block.hpp b/boost/asio/detail/win_fenced_block.hpp
index c6b94c5795..dba1d5355d 100644
--- a/boost/asio/detail/win_fenced_block.hpp
+++ b/boost/asio/detail/win_fenced_block.hpp
@@ -2,7 +2,7 @@
// detail/win_fenced_block.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_handle_read_op.hpp b/boost/asio/detail/win_iocp_handle_read_op.hpp
index 23a0437ca9..fda3cc1e77 100644
--- a/boost/asio/detail/win_iocp_handle_read_op.hpp
+++ b/boost/asio/detail/win_iocp_handle_read_op.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_handle_read_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/win_iocp_handle_service.hpp b/boost/asio/detail/win_iocp_handle_service.hpp
index aeb42449d4..29f24f90c5 100644
--- a/boost/asio/detail/win_iocp_handle_service.hpp
+++ b/boost/asio/detail/win_iocp_handle_service.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_handle_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/win_iocp_handle_write_op.hpp b/boost/asio/detail/win_iocp_handle_write_op.hpp
index 284d02f53d..a53db910a8 100644
--- a/boost/asio/detail/win_iocp_handle_write_op.hpp
+++ b/boost/asio/detail/win_iocp_handle_write_op.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_handle_write_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/win_iocp_io_service.hpp b/boost/asio/detail/win_iocp_io_service.hpp
index 812545f6ee..0abb9fe89a 100644
--- a/boost/asio/detail/win_iocp_io_service.hpp
+++ b/boost/asio/detail/win_iocp_io_service.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_io_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_null_buffers_op.hpp b/boost/asio/detail/win_iocp_null_buffers_op.hpp
index f113dcf664..905d7a664e 100644
--- a/boost/asio/detail/win_iocp_null_buffers_op.hpp
+++ b/boost/asio/detail/win_iocp_null_buffers_op.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_null_buffers_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_operation.hpp b/boost/asio/detail/win_iocp_operation.hpp
index 738e060258..232930344b 100644
--- a/boost/asio/detail/win_iocp_operation.hpp
+++ b/boost/asio/detail/win_iocp_operation.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_operation.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_overlapped_op.hpp b/boost/asio/detail/win_iocp_overlapped_op.hpp
index 758954bd87..6d0e4bfcc2 100644
--- a/boost/asio/detail/win_iocp_overlapped_op.hpp
+++ b/boost/asio/detail/win_iocp_overlapped_op.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_overlapped_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_overlapped_ptr.hpp b/boost/asio/detail/win_iocp_overlapped_ptr.hpp
index 822db2084c..5d252c6fb1 100644
--- a/boost/asio/detail/win_iocp_overlapped_ptr.hpp
+++ b/boost/asio/detail/win_iocp_overlapped_ptr.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_overlapped_ptr.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_serial_port_service.hpp b/boost/asio/detail/win_iocp_serial_port_service.hpp
index e127307769..6b21f96535 100644
--- a/boost/asio/detail/win_iocp_serial_port_service.hpp
+++ b/boost/asio/detail/win_iocp_serial_port_service.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_serial_port_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/win_iocp_socket_accept_op.hpp b/boost/asio/detail/win_iocp_socket_accept_op.hpp
index 8ea3cebafb..d296103c54 100644
--- a/boost/asio/detail/win_iocp_socket_accept_op.hpp
+++ b/boost/asio/detail/win_iocp_socket_accept_op.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_socket_accept_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_socket_connect_op.hpp b/boost/asio/detail/win_iocp_socket_connect_op.hpp
index 66b4cbf9d8..e987c6b6c4 100644
--- a/boost/asio/detail/win_iocp_socket_connect_op.hpp
+++ b/boost/asio/detail/win_iocp_socket_connect_op.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_socket_connect_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_socket_recv_op.hpp b/boost/asio/detail/win_iocp_socket_recv_op.hpp
index fca5a5f76c..4202822d17 100644
--- a/boost/asio/detail/win_iocp_socket_recv_op.hpp
+++ b/boost/asio/detail/win_iocp_socket_recv_op.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_socket_recv_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp b/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp
index dd9bf1ef65..21ca4fb331 100644
--- a/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp
+++ b/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_socket_recvfrom_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp b/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp
index 6345cbe977..5179bb2945 100644
--- a/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp
+++ b/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_socket_recvmsg_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_socket_send_op.hpp b/boost/asio/detail/win_iocp_socket_send_op.hpp
index 1c76b786d5..c9abc0e664 100644
--- a/boost/asio/detail/win_iocp_socket_send_op.hpp
+++ b/boost/asio/detail/win_iocp_socket_send_op.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_socket_send_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_socket_service.hpp b/boost/asio/detail/win_iocp_socket_service.hpp
index 1f3f8fcb94..179798c8d9 100644
--- a/boost/asio/detail/win_iocp_socket_service.hpp
+++ b/boost/asio/detail/win_iocp_socket_service.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_socket_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -169,6 +169,7 @@ public:
// Move-construct a new socket implementation from another protocol type.
template <typename Protocol1>
void converting_move_construct(implementation_type& impl,
+ win_iocp_socket_service<Protocol1>&,
typename win_iocp_socket_service<
Protocol1>::implementation_type& other_impl)
{
diff --git a/boost/asio/detail/win_iocp_socket_service_base.hpp b/boost/asio/detail/win_iocp_socket_service_base.hpp
index 18b3fb874a..8ecf219598 100644
--- a/boost/asio/detail/win_iocp_socket_service_base.hpp
+++ b/boost/asio/detail/win_iocp_socket_service_base.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_socket_service_base.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_iocp_thread_info.hpp b/boost/asio/detail/win_iocp_thread_info.hpp
index a954df1538..d8b77c9a6c 100644
--- a/boost/asio/detail/win_iocp_thread_info.hpp
+++ b/boost/asio/detail/win_iocp_thread_info.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_thread_info.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_mutex.hpp b/boost/asio/detail/win_mutex.hpp
index aa6549cecf..1bf99ec0e0 100644
--- a/boost/asio/detail/win_mutex.hpp
+++ b/boost/asio/detail/win_mutex.hpp
@@ -2,7 +2,7 @@
// detail/win_mutex.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_object_handle_service.hpp b/boost/asio/detail/win_object_handle_service.hpp
index f12a002a92..3383657304 100644
--- a/boost/asio/detail/win_object_handle_service.hpp
+++ b/boost/asio/detail/win_object_handle_service.hpp
@@ -2,7 +2,7 @@
// detail/win_object_handle_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2011 Boris Schaeling (boris@highscore.de)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/detail/win_static_mutex.hpp b/boost/asio/detail/win_static_mutex.hpp
index aa19d4ef97..5f0099705d 100644
--- a/boost/asio/detail/win_static_mutex.hpp
+++ b/boost/asio/detail/win_static_mutex.hpp
@@ -2,7 +2,7 @@
// detail/win_static_mutex.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_thread.hpp b/boost/asio/detail/win_thread.hpp
index 0b42245ce3..a138d92ee8 100644
--- a/boost/asio/detail/win_thread.hpp
+++ b/boost/asio/detail/win_thread.hpp
@@ -2,7 +2,7 @@
// detail/win_thread.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/win_tss_ptr.hpp b/boost/asio/detail/win_tss_ptr.hpp
index ca7aac0a5e..99200d0a90 100644
--- a/boost/asio/detail/win_tss_ptr.hpp
+++ b/boost/asio/detail/win_tss_ptr.hpp
@@ -2,7 +2,7 @@
// detail/win_tss_ptr.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/winapi_thread.hpp b/boost/asio/detail/winapi_thread.hpp
index b74f18f54f..204e73f42a 100644
--- a/boost/asio/detail/winapi_thread.hpp
+++ b/boost/asio/detail/winapi_thread.hpp
@@ -2,7 +2,7 @@
// detail/winapi_thread.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/winrt_async_manager.hpp b/boost/asio/detail/winrt_async_manager.hpp
index 1838a8973d..d6d823d689 100644
--- a/boost/asio/detail/winrt_async_manager.hpp
+++ b/boost/asio/detail/winrt_async_manager.hpp
@@ -2,7 +2,7 @@
// detail/winrt_async_manager.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/winrt_async_op.hpp b/boost/asio/detail/winrt_async_op.hpp
index 012c6eaad6..078016ebc7 100644
--- a/boost/asio/detail/winrt_async_op.hpp
+++ b/boost/asio/detail/winrt_async_op.hpp
@@ -2,7 +2,7 @@
// detail/winrt_async_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/winrt_resolve_op.hpp b/boost/asio/detail/winrt_resolve_op.hpp
index 0f255b1bbf..12d56933b1 100644
--- a/boost/asio/detail/winrt_resolve_op.hpp
+++ b/boost/asio/detail/winrt_resolve_op.hpp
@@ -2,7 +2,7 @@
// detail/winrt_resolve_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/winrt_resolver_service.hpp b/boost/asio/detail/winrt_resolver_service.hpp
index f476bec963..dfd1dddeb2 100644
--- a/boost/asio/detail/winrt_resolver_service.hpp
+++ b/boost/asio/detail/winrt_resolver_service.hpp
@@ -2,7 +2,7 @@
// detail/winrt_resolver_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/winrt_socket_connect_op.hpp b/boost/asio/detail/winrt_socket_connect_op.hpp
index f2472c53f5..548f7d631a 100644
--- a/boost/asio/detail/winrt_socket_connect_op.hpp
+++ b/boost/asio/detail/winrt_socket_connect_op.hpp
@@ -2,7 +2,7 @@
// detail/winrt_socket_connect_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/winrt_socket_recv_op.hpp b/boost/asio/detail/winrt_socket_recv_op.hpp
index 46de1f96a6..2cbbb3c8d8 100644
--- a/boost/asio/detail/winrt_socket_recv_op.hpp
+++ b/boost/asio/detail/winrt_socket_recv_op.hpp
@@ -2,7 +2,7 @@
// detail/winrt_socket_recv_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/winrt_socket_send_op.hpp b/boost/asio/detail/winrt_socket_send_op.hpp
index 77b19517fe..591d9536c3 100644
--- a/boost/asio/detail/winrt_socket_send_op.hpp
+++ b/boost/asio/detail/winrt_socket_send_op.hpp
@@ -2,7 +2,7 @@
// detail/winrt_socket_send_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/winrt_ssocket_service.hpp b/boost/asio/detail/winrt_ssocket_service.hpp
index a39cf96b2b..b9b1910e78 100644
--- a/boost/asio/detail/winrt_ssocket_service.hpp
+++ b/boost/asio/detail/winrt_ssocket_service.hpp
@@ -2,7 +2,7 @@
// detail/winrt_ssocket_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -90,6 +90,7 @@ public:
// Move-construct a new socket implementation from another protocol type.
template <typename Protocol1>
void converting_move_construct(implementation_type& impl,
+ winrt_ssocket_service<Protocol1>&,
typename winrt_ssocket_service<
Protocol1>::implementation_type& other_impl)
{
diff --git a/boost/asio/detail/winrt_ssocket_service_base.hpp b/boost/asio/detail/winrt_ssocket_service_base.hpp
index 8bc9852d72..88e5674576 100644
--- a/boost/asio/detail/winrt_ssocket_service_base.hpp
+++ b/boost/asio/detail/winrt_ssocket_service_base.hpp
@@ -2,7 +2,7 @@
// detail/winrt_ssocket_service_base.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/winrt_timer_scheduler.hpp b/boost/asio/detail/winrt_timer_scheduler.hpp
index a83aae3331..8b119b2724 100644
--- a/boost/asio/detail/winrt_timer_scheduler.hpp
+++ b/boost/asio/detail/winrt_timer_scheduler.hpp
@@ -2,7 +2,7 @@
// detail/winrt_timer_scheduler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/winrt_utils.hpp b/boost/asio/detail/winrt_utils.hpp
index 07c64626cb..351aa62f23 100644
--- a/boost/asio/detail/winrt_utils.hpp
+++ b/boost/asio/detail/winrt_utils.hpp
@@ -2,7 +2,7 @@
// detail/winrt_utils.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/winsock_init.hpp b/boost/asio/detail/winsock_init.hpp
index 4f56988bf6..23688366c5 100644
--- a/boost/asio/detail/winsock_init.hpp
+++ b/boost/asio/detail/winsock_init.hpp
@@ -2,7 +2,7 @@
// detail/winsock_init.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/detail/wrapped_handler.hpp b/boost/asio/detail/wrapped_handler.hpp
index 14056eb953..28f1b01020 100644
--- a/boost/asio/detail/wrapped_handler.hpp
+++ b/boost/asio/detail/wrapped_handler.hpp
@@ -2,7 +2,7 @@
// detail/wrapped_handler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/error.hpp b/boost/asio/error.hpp
index 830d2818d2..dd338fb156 100644
--- a/boost/asio/error.hpp
+++ b/boost/asio/error.hpp
@@ -2,7 +2,7 @@
// error.hpp
// ~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -255,13 +255,17 @@ inline const boost::system::error_category& get_addrinfo_category()
extern BOOST_ASIO_DECL
const boost::system::error_category& get_misc_category();
-static const boost::system::error_category& system_category
+static const boost::system::error_category&
+ system_category BOOST_ASIO_UNUSED_VARIABLE
= boost::asio::error::get_system_category();
-static const boost::system::error_category& netdb_category
+static const boost::system::error_category&
+ netdb_category BOOST_ASIO_UNUSED_VARIABLE
= boost::asio::error::get_netdb_category();
-static const boost::system::error_category& addrinfo_category
+static const boost::system::error_category&
+ addrinfo_category BOOST_ASIO_UNUSED_VARIABLE
= boost::asio::error::get_addrinfo_category();
-static const boost::system::error_category& misc_category
+static const boost::system::error_category&
+ misc_category BOOST_ASIO_UNUSED_VARIABLE
= boost::asio::error::get_misc_category();
} // namespace error
diff --git a/boost/asio/generic/basic_endpoint.hpp b/boost/asio/generic/basic_endpoint.hpp
index 10bbd629d6..3c9b294f9a 100644
--- a/boost/asio/generic/basic_endpoint.hpp
+++ b/boost/asio/generic/basic_endpoint.hpp
@@ -2,7 +2,7 @@
// generic/basic_endpoint.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/generic/datagram_protocol.hpp b/boost/asio/generic/datagram_protocol.hpp
index cd46ed5b63..16f170544b 100644
--- a/boost/asio/generic/datagram_protocol.hpp
+++ b/boost/asio/generic/datagram_protocol.hpp
@@ -2,7 +2,7 @@
// generic/datagram_protocol.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/generic/detail/endpoint.hpp b/boost/asio/generic/detail/endpoint.hpp
index f28e5349ad..5496ef557c 100644
--- a/boost/asio/generic/detail/endpoint.hpp
+++ b/boost/asio/generic/detail/endpoint.hpp
@@ -2,7 +2,7 @@
// generic/detail/endpoint.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/generic/detail/impl/endpoint.ipp b/boost/asio/generic/detail/impl/endpoint.ipp
index 27f33d47fc..3c2da4a608 100644
--- a/boost/asio/generic/detail/impl/endpoint.ipp
+++ b/boost/asio/generic/detail/impl/endpoint.ipp
@@ -2,7 +2,7 @@
// generic/detail/impl/endpoint.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/generic/raw_protocol.hpp b/boost/asio/generic/raw_protocol.hpp
index f85b5499c4..0cd9d50be3 100644
--- a/boost/asio/generic/raw_protocol.hpp
+++ b/boost/asio/generic/raw_protocol.hpp
@@ -2,7 +2,7 @@
// generic/raw_protocol.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/generic/seq_packet_protocol.hpp b/boost/asio/generic/seq_packet_protocol.hpp
index f320acb90e..13ecd8ae73 100644
--- a/boost/asio/generic/seq_packet_protocol.hpp
+++ b/boost/asio/generic/seq_packet_protocol.hpp
@@ -2,7 +2,7 @@
// generic/seq_packet_protocol.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/generic/stream_protocol.hpp b/boost/asio/generic/stream_protocol.hpp
index 63c31d9754..f57131a24d 100644
--- a/boost/asio/generic/stream_protocol.hpp
+++ b/boost/asio/generic/stream_protocol.hpp
@@ -2,7 +2,7 @@
// generic/stream_protocol.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/handler_alloc_hook.hpp b/boost/asio/handler_alloc_hook.hpp
index 8f7fb7f65d..84071d0378 100644
--- a/boost/asio/handler_alloc_hook.hpp
+++ b/boost/asio/handler_alloc_hook.hpp
@@ -2,7 +2,7 @@
// handler_alloc_hook.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/handler_continuation_hook.hpp b/boost/asio/handler_continuation_hook.hpp
index 8b660ec3bb..da516bc205 100644
--- a/boost/asio/handler_continuation_hook.hpp
+++ b/boost/asio/handler_continuation_hook.hpp
@@ -2,7 +2,7 @@
// handler_continuation_hook.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/handler_invoke_hook.hpp b/boost/asio/handler_invoke_hook.hpp
index 8d28a739c3..6605d87499 100644
--- a/boost/asio/handler_invoke_hook.hpp
+++ b/boost/asio/handler_invoke_hook.hpp
@@ -2,7 +2,7 @@
// handler_invoke_hook.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/handler_type.hpp b/boost/asio/handler_type.hpp
index e4f2de8817..11e97e3ea0 100644
--- a/boost/asio/handler_type.hpp
+++ b/boost/asio/handler_type.hpp
@@ -2,7 +2,7 @@
// handler_type.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/high_resolution_timer.hpp b/boost/asio/high_resolution_timer.hpp
index e319fae8c8..5d6cef0296 100644
--- a/boost/asio/high_resolution_timer.hpp
+++ b/boost/asio/high_resolution_timer.hpp
@@ -2,7 +2,7 @@
// high_resolution_timer.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/buffered_read_stream.hpp b/boost/asio/impl/buffered_read_stream.hpp
index f1fde031c4..082ed0338b 100644
--- a/boost/asio/impl/buffered_read_stream.hpp
+++ b/boost/asio/impl/buffered_read_stream.hpp
@@ -2,7 +2,7 @@
// impl/buffered_read_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/buffered_write_stream.hpp b/boost/asio/impl/buffered_write_stream.hpp
index af741067b6..22585eb6ce 100644
--- a/boost/asio/impl/buffered_write_stream.hpp
+++ b/boost/asio/impl/buffered_write_stream.hpp
@@ -2,7 +2,7 @@
// impl/buffered_write_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/connect.hpp b/boost/asio/impl/connect.hpp
index e1c0775203..ba587eca02 100644
--- a/boost/asio/impl/connect.hpp
+++ b/boost/asio/impl/connect.hpp
@@ -2,7 +2,7 @@
// impl/connect.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/error.ipp b/boost/asio/impl/error.ipp
index 12ccf6f285..8626aded6a 100644
--- a/boost/asio/impl/error.ipp
+++ b/boost/asio/impl/error.ipp
@@ -2,7 +2,7 @@
// impl/error.ipp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/handler_alloc_hook.ipp b/boost/asio/impl/handler_alloc_hook.ipp
index c60ea51a96..ddc84c75cf 100644
--- a/boost/asio/impl/handler_alloc_hook.ipp
+++ b/boost/asio/impl/handler_alloc_hook.ipp
@@ -2,7 +2,7 @@
// impl/handler_alloc_hook.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/io_service.hpp b/boost/asio/impl/io_service.hpp
index 1e76497b3b..beee3f3978 100644
--- a/boost/asio/impl/io_service.hpp
+++ b/boost/asio/impl/io_service.hpp
@@ -2,7 +2,7 @@
// impl/io_service.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/io_service.ipp b/boost/asio/impl/io_service.ipp
index 5f287a0d5e..428db3f879 100644
--- a/boost/asio/impl/io_service.ipp
+++ b/boost/asio/impl/io_service.ipp
@@ -2,7 +2,7 @@
// impl/io_service.ipp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/read.hpp b/boost/asio/impl/read.hpp
index 6ee7e41c4e..8648e47918 100644
--- a/boost/asio/impl/read.hpp
+++ b/boost/asio/impl/read.hpp
@@ -2,7 +2,7 @@
// impl/read.hpp
// ~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/read_at.hpp b/boost/asio/impl/read_at.hpp
index 783cfc8d54..0ec8a94e44 100644
--- a/boost/asio/impl/read_at.hpp
+++ b/boost/asio/impl/read_at.hpp
@@ -2,7 +2,7 @@
// impl/read_at.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/read_until.hpp b/boost/asio/impl/read_until.hpp
index ade51a2bb6..737dedcdf2 100644
--- a/boost/asio/impl/read_until.hpp
+++ b/boost/asio/impl/read_until.hpp
@@ -2,7 +2,7 @@
// impl/read_until.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/serial_port_base.hpp b/boost/asio/impl/serial_port_base.hpp
index 8826acb524..a138011347 100644
--- a/boost/asio/impl/serial_port_base.hpp
+++ b/boost/asio/impl/serial_port_base.hpp
@@ -2,7 +2,7 @@
// impl/serial_port_base.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/impl/serial_port_base.ipp b/boost/asio/impl/serial_port_base.ipp
index fae804bd0e..fcb6ce3df4 100644
--- a/boost/asio/impl/serial_port_base.ipp
+++ b/boost/asio/impl/serial_port_base.ipp
@@ -2,7 +2,7 @@
// impl/serial_port_base.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/impl/spawn.hpp b/boost/asio/impl/spawn.hpp
index f8e5a9e435..a42fc6fbad 100644
--- a/boost/asio/impl/spawn.hpp
+++ b/boost/asio/impl/spawn.hpp
@@ -2,7 +2,7 @@
// impl/spawn.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/src.cpp b/boost/asio/impl/src.cpp
index 9c08fb3ea1..1b76dd83c4 100644
--- a/boost/asio/impl/src.cpp
+++ b/boost/asio/impl/src.cpp
@@ -2,7 +2,7 @@
// impl/src.cpp
// ~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/src.hpp b/boost/asio/impl/src.hpp
index 137e7f6234..7b9a03eda9 100644
--- a/boost/asio/impl/src.hpp
+++ b/boost/asio/impl/src.hpp
@@ -2,7 +2,7 @@
// impl/src.hpp
// ~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/use_future.hpp b/boost/asio/impl/use_future.hpp
index 92106f4704..c74050ea63 100644
--- a/boost/asio/impl/use_future.hpp
+++ b/boost/asio/impl/use_future.hpp
@@ -2,7 +2,7 @@
// impl/use_future.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -21,6 +21,7 @@
#include <boost/system/error_code.hpp>
#include <boost/asio/handler_type.hpp>
#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -37,9 +38,9 @@ namespace detail {
template <typename Alloc>
promise_handler(use_future_t<Alloc> uf)
: promise_(std::allocate_shared<std::promise<T> >(
- typename Alloc::template rebind<char>::other(uf.get_allocator()),
+ BOOST_ASIO_REBIND_ALLOC(Alloc, char)(uf.get_allocator()),
std::allocator_arg,
- typename Alloc::template rebind<char>::other(uf.get_allocator())))
+ BOOST_ASIO_REBIND_ALLOC(Alloc, char)(uf.get_allocator())))
{
}
@@ -71,9 +72,9 @@ namespace detail {
template <typename Alloc>
promise_handler(use_future_t<Alloc> uf)
: promise_(std::allocate_shared<std::promise<void> >(
- typename Alloc::template rebind<char>::other(uf.get_allocator()),
+ BOOST_ASIO_REBIND_ALLOC(Alloc, char)(uf.get_allocator()),
std::allocator_arg,
- typename Alloc::template rebind<char>::other(uf.get_allocator())))
+ BOOST_ASIO_REBIND_ALLOC(Alloc, char)(uf.get_allocator())))
{
}
diff --git a/boost/asio/impl/write.hpp b/boost/asio/impl/write.hpp
index ead03d87b7..84313fed09 100644
--- a/boost/asio/impl/write.hpp
+++ b/boost/asio/impl/write.hpp
@@ -2,7 +2,7 @@
// impl/write.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/write_at.hpp b/boost/asio/impl/write_at.hpp
index 18cf4ab597..20e95d9338 100644
--- a/boost/asio/impl/write_at.hpp
+++ b/boost/asio/impl/write_at.hpp
@@ -2,7 +2,7 @@
// impl/write_at.hpp
// ~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/io_service.hpp b/boost/asio/io_service.hpp
index 1226530cfe..f2b4667311 100644
--- a/boost/asio/io_service.hpp
+++ b/boost/asio/io_service.hpp
@@ -2,7 +2,7 @@
// io_service.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/address.hpp b/boost/asio/ip/address.hpp
index 858c375373..6e1b19e650 100644
--- a/boost/asio/ip/address.hpp
+++ b/boost/asio/ip/address.hpp
@@ -2,7 +2,7 @@
// ip/address.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/address_v4.hpp b/boost/asio/ip/address_v4.hpp
index a010014807..3db4d4c825 100644
--- a/boost/asio/ip/address_v4.hpp
+++ b/boost/asio/ip/address_v4.hpp
@@ -2,7 +2,7 @@
// ip/address_v4.hpp
// ~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/address_v6.hpp b/boost/asio/ip/address_v6.hpp
index 35a86e423a..10e9bc1594 100644
--- a/boost/asio/ip/address_v6.hpp
+++ b/boost/asio/ip/address_v6.hpp
@@ -2,7 +2,7 @@
// ip/address_v6.hpp
// ~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/basic_endpoint.hpp b/boost/asio/ip/basic_endpoint.hpp
index 35075daf7d..235b178589 100644
--- a/boost/asio/ip/basic_endpoint.hpp
+++ b/boost/asio/ip/basic_endpoint.hpp
@@ -2,7 +2,7 @@
// ip/basic_endpoint.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/basic_resolver.hpp b/boost/asio/ip/basic_resolver.hpp
index e930c73693..c5941de4f1 100644
--- a/boost/asio/ip/basic_resolver.hpp
+++ b/boost/asio/ip/basic_resolver.hpp
@@ -2,7 +2,7 @@
// ip/basic_resolver.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/basic_resolver_entry.hpp b/boost/asio/ip/basic_resolver_entry.hpp
index 79733dcd64..05c8547a0c 100644
--- a/boost/asio/ip/basic_resolver_entry.hpp
+++ b/boost/asio/ip/basic_resolver_entry.hpp
@@ -2,7 +2,7 @@
// ip/basic_resolver_entry.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/basic_resolver_iterator.hpp b/boost/asio/ip/basic_resolver_iterator.hpp
index 84c0e94fc1..b7deb77364 100644
--- a/boost/asio/ip/basic_resolver_iterator.hpp
+++ b/boost/asio/ip/basic_resolver_iterator.hpp
@@ -2,7 +2,7 @@
// ip/basic_resolver_iterator.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/basic_resolver_query.hpp b/boost/asio/ip/basic_resolver_query.hpp
index 0ba6d7b9cb..4f1b66d274 100644
--- a/boost/asio/ip/basic_resolver_query.hpp
+++ b/boost/asio/ip/basic_resolver_query.hpp
@@ -2,7 +2,7 @@
// ip/basic_resolver_query.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/detail/endpoint.hpp b/boost/asio/ip/detail/endpoint.hpp
index 4fea9feb47..0a354e12a9 100644
--- a/boost/asio/ip/detail/endpoint.hpp
+++ b/boost/asio/ip/detail/endpoint.hpp
@@ -2,7 +2,7 @@
// ip/detail/endpoint.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/detail/impl/endpoint.ipp b/boost/asio/ip/detail/impl/endpoint.ipp
index 02a5a82558..f1f9309af5 100644
--- a/boost/asio/ip/detail/impl/endpoint.ipp
+++ b/boost/asio/ip/detail/impl/endpoint.ipp
@@ -2,7 +2,7 @@
// ip/detail/impl/endpoint.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -58,13 +58,13 @@ endpoint::endpoint(int family, unsigned short port_num)
boost::asio::detail::socket_ops::host_to_network_short(port_num);
data_.v6.sin6_flowinfo = 0;
data_.v6.sin6_addr.s6_addr[0] = 0; data_.v6.sin6_addr.s6_addr[1] = 0;
- data_.v6.sin6_addr.s6_addr[2] = 0, data_.v6.sin6_addr.s6_addr[3] = 0;
- data_.v6.sin6_addr.s6_addr[4] = 0, data_.v6.sin6_addr.s6_addr[5] = 0;
- data_.v6.sin6_addr.s6_addr[6] = 0, data_.v6.sin6_addr.s6_addr[7] = 0;
- data_.v6.sin6_addr.s6_addr[8] = 0, data_.v6.sin6_addr.s6_addr[9] = 0;
- data_.v6.sin6_addr.s6_addr[10] = 0, data_.v6.sin6_addr.s6_addr[11] = 0;
- data_.v6.sin6_addr.s6_addr[12] = 0, data_.v6.sin6_addr.s6_addr[13] = 0;
- data_.v6.sin6_addr.s6_addr[14] = 0, data_.v6.sin6_addr.s6_addr[15] = 0;
+ data_.v6.sin6_addr.s6_addr[2] = 0; data_.v6.sin6_addr.s6_addr[3] = 0;
+ data_.v6.sin6_addr.s6_addr[4] = 0; data_.v6.sin6_addr.s6_addr[5] = 0;
+ data_.v6.sin6_addr.s6_addr[6] = 0; data_.v6.sin6_addr.s6_addr[7] = 0;
+ data_.v6.sin6_addr.s6_addr[8] = 0; data_.v6.sin6_addr.s6_addr[9] = 0;
+ data_.v6.sin6_addr.s6_addr[10] = 0; data_.v6.sin6_addr.s6_addr[11] = 0;
+ data_.v6.sin6_addr.s6_addr[12] = 0; data_.v6.sin6_addr.s6_addr[13] = 0;
+ data_.v6.sin6_addr.s6_addr[14] = 0; data_.v6.sin6_addr.s6_addr[15] = 0;
data_.v6.sin6_scope_id = 0;
}
}
diff --git a/boost/asio/ip/detail/socket_option.hpp b/boost/asio/ip/detail/socket_option.hpp
index 597e7e3bc0..e8849fda92 100644
--- a/boost/asio/ip/detail/socket_option.hpp
+++ b/boost/asio/ip/detail/socket_option.hpp
@@ -2,7 +2,7 @@
// detail/socket_option.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/host_name.hpp b/boost/asio/ip/host_name.hpp
index 0050726669..69106eeb35 100644
--- a/boost/asio/ip/host_name.hpp
+++ b/boost/asio/ip/host_name.hpp
@@ -2,7 +2,7 @@
// ip/host_name.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/icmp.hpp b/boost/asio/ip/icmp.hpp
index 901fb0240e..fa8da94777 100644
--- a/boost/asio/ip/icmp.hpp
+++ b/boost/asio/ip/icmp.hpp
@@ -2,7 +2,7 @@
// ip/icmp.hpp
// ~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/impl/address.hpp b/boost/asio/ip/impl/address.hpp
index c25f845139..e595d7063b 100644
--- a/boost/asio/ip/impl/address.hpp
+++ b/boost/asio/ip/impl/address.hpp
@@ -2,7 +2,7 @@
// ip/impl/address.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/impl/address.ipp b/boost/asio/ip/impl/address.ipp
index 3fbfbfd04b..5eda3e9ecf 100644
--- a/boost/asio/ip/impl/address.ipp
+++ b/boost/asio/ip/impl/address.ipp
@@ -2,7 +2,7 @@
// ip/impl/address.ipp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/impl/address_v4.hpp b/boost/asio/ip/impl/address_v4.hpp
index 722d000ead..028b69b676 100644
--- a/boost/asio/ip/impl/address_v4.hpp
+++ b/boost/asio/ip/impl/address_v4.hpp
@@ -2,7 +2,7 @@
// ip/impl/address_v4.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/impl/address_v4.ipp b/boost/asio/ip/impl/address_v4.ipp
index c7fddf5429..440217bcb2 100644
--- a/boost/asio/ip/impl/address_v4.ipp
+++ b/boost/asio/ip/impl/address_v4.ipp
@@ -2,7 +2,7 @@
// ip/impl/address_v4.ipp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/impl/address_v6.hpp b/boost/asio/ip/impl/address_v6.hpp
index c1b6bbc986..4b88129c50 100644
--- a/boost/asio/ip/impl/address_v6.hpp
+++ b/boost/asio/ip/impl/address_v6.hpp
@@ -2,7 +2,7 @@
// ip/impl/address_v6.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/impl/address_v6.ipp b/boost/asio/ip/impl/address_v6.ipp
index 1b6a6adbd5..2d1a1974bf 100644
--- a/boost/asio/ip/impl/address_v6.ipp
+++ b/boost/asio/ip/impl/address_v6.ipp
@@ -2,7 +2,7 @@
// ip/impl/address_v6.ipp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/impl/basic_endpoint.hpp b/boost/asio/ip/impl/basic_endpoint.hpp
index a0ff034a43..4d9c4505c3 100644
--- a/boost/asio/ip/impl/basic_endpoint.hpp
+++ b/boost/asio/ip/impl/basic_endpoint.hpp
@@ -2,7 +2,7 @@
// ip/impl/basic_endpoint.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/impl/host_name.ipp b/boost/asio/ip/impl/host_name.ipp
index aab0f2f472..ab85f41793 100644
--- a/boost/asio/ip/impl/host_name.ipp
+++ b/boost/asio/ip/impl/host_name.ipp
@@ -2,7 +2,7 @@
// ip/impl/host_name.ipp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/multicast.hpp b/boost/asio/ip/multicast.hpp
index e5c2f07037..d82e442116 100644
--- a/boost/asio/ip/multicast.hpp
+++ b/boost/asio/ip/multicast.hpp
@@ -2,7 +2,7 @@
// ip/multicast.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/resolver_query_base.hpp b/boost/asio/ip/resolver_query_base.hpp
index e894278e72..fd74059772 100644
--- a/boost/asio/ip/resolver_query_base.hpp
+++ b/boost/asio/ip/resolver_query_base.hpp
@@ -2,7 +2,7 @@
// ip/resolver_query_base.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/resolver_service.hpp b/boost/asio/ip/resolver_service.hpp
index f894ffb8fc..b4aa4d25bb 100644
--- a/boost/asio/ip/resolver_service.hpp
+++ b/boost/asio/ip/resolver_service.hpp
@@ -2,7 +2,7 @@
// ip/resolver_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/tcp.hpp b/boost/asio/ip/tcp.hpp
index 71c6fb921c..079ec46a25 100644
--- a/boost/asio/ip/tcp.hpp
+++ b/boost/asio/ip/tcp.hpp
@@ -2,7 +2,7 @@
// ip/tcp.hpp
// ~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/udp.hpp b/boost/asio/ip/udp.hpp
index 4642b1c7d1..c63bc986eb 100644
--- a/boost/asio/ip/udp.hpp
+++ b/boost/asio/ip/udp.hpp
@@ -2,7 +2,7 @@
// ip/udp.hpp
// ~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/unicast.hpp b/boost/asio/ip/unicast.hpp
index 1755a49b74..4a9df8bfd2 100644
--- a/boost/asio/ip/unicast.hpp
+++ b/boost/asio/ip/unicast.hpp
@@ -2,7 +2,7 @@
// ip/unicast.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ip/v6_only.hpp b/boost/asio/ip/v6_only.hpp
index 4f9b218686..b22c9a5db8 100644
--- a/boost/asio/ip/v6_only.hpp
+++ b/boost/asio/ip/v6_only.hpp
@@ -2,7 +2,7 @@
// ip/v6_only.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/is_read_buffered.hpp b/boost/asio/is_read_buffered.hpp
index aea0049145..c2d45a0ab6 100644
--- a/boost/asio/is_read_buffered.hpp
+++ b/boost/asio/is_read_buffered.hpp
@@ -2,7 +2,7 @@
// is_read_buffered.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/is_write_buffered.hpp b/boost/asio/is_write_buffered.hpp
index 0a3279c934..1f462cd6ca 100644
--- a/boost/asio/is_write_buffered.hpp
+++ b/boost/asio/is_write_buffered.hpp
@@ -2,7 +2,7 @@
// is_write_buffered.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/local/basic_endpoint.hpp b/boost/asio/local/basic_endpoint.hpp
index a5dd34f355..9fa281f70b 100644
--- a/boost/asio/local/basic_endpoint.hpp
+++ b/boost/asio/local/basic_endpoint.hpp
@@ -2,7 +2,7 @@
// local/basic_endpoint.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Derived from a public domain implementation written by Daniel Casimiro.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/local/connect_pair.hpp b/boost/asio/local/connect_pair.hpp
index c3a5bc6627..333c758783 100644
--- a/boost/asio/local/connect_pair.hpp
+++ b/boost/asio/local/connect_pair.hpp
@@ -2,7 +2,7 @@
// local/connect_pair.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/local/datagram_protocol.hpp b/boost/asio/local/datagram_protocol.hpp
index faf42ef62a..3d0fa08ec6 100644
--- a/boost/asio/local/datagram_protocol.hpp
+++ b/boost/asio/local/datagram_protocol.hpp
@@ -2,7 +2,7 @@
// local/datagram_protocol.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/local/detail/endpoint.hpp b/boost/asio/local/detail/endpoint.hpp
index 04e077baf5..68893fb1b1 100644
--- a/boost/asio/local/detail/endpoint.hpp
+++ b/boost/asio/local/detail/endpoint.hpp
@@ -2,7 +2,7 @@
// local/detail/endpoint.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Derived from a public domain implementation written by Daniel Casimiro.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/local/detail/impl/endpoint.ipp b/boost/asio/local/detail/impl/endpoint.ipp
index 98a0c14f5a..4173a8242e 100644
--- a/boost/asio/local/detail/impl/endpoint.ipp
+++ b/boost/asio/local/detail/impl/endpoint.ipp
@@ -2,7 +2,7 @@
// local/detail/impl/endpoint.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Derived from a public domain implementation written by Daniel Casimiro.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/local/stream_protocol.hpp b/boost/asio/local/stream_protocol.hpp
index 655a8b306c..eac968311b 100644
--- a/boost/asio/local/stream_protocol.hpp
+++ b/boost/asio/local/stream_protocol.hpp
@@ -2,7 +2,7 @@
// local/stream_protocol.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/placeholders.hpp b/boost/asio/placeholders.hpp
index 36a36b0c65..8714e3454a 100644
--- a/boost/asio/placeholders.hpp
+++ b/boost/asio/placeholders.hpp
@@ -2,7 +2,7 @@
// placeholders.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/posix/basic_descriptor.hpp b/boost/asio/posix/basic_descriptor.hpp
index 896d00d8c3..a857c237a3 100644
--- a/boost/asio/posix/basic_descriptor.hpp
+++ b/boost/asio/posix/basic_descriptor.hpp
@@ -2,7 +2,7 @@
// posix/basic_descriptor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/posix/basic_stream_descriptor.hpp b/boost/asio/posix/basic_stream_descriptor.hpp
index 4b8498de67..4baacb519b 100644
--- a/boost/asio/posix/basic_stream_descriptor.hpp
+++ b/boost/asio/posix/basic_stream_descriptor.hpp
@@ -2,7 +2,7 @@
// posix/basic_stream_descriptor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/posix/descriptor_base.hpp b/boost/asio/posix/descriptor_base.hpp
index d9e8fbd6a4..e23af43bc8 100644
--- a/boost/asio/posix/descriptor_base.hpp
+++ b/boost/asio/posix/descriptor_base.hpp
@@ -2,7 +2,7 @@
// posix/descriptor_base.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/posix/stream_descriptor.hpp b/boost/asio/posix/stream_descriptor.hpp
index 9708489577..d6d1344702 100644
--- a/boost/asio/posix/stream_descriptor.hpp
+++ b/boost/asio/posix/stream_descriptor.hpp
@@ -2,7 +2,7 @@
// posix/stream_descriptor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/posix/stream_descriptor_service.hpp b/boost/asio/posix/stream_descriptor_service.hpp
index 364fbdae31..e42580d3f3 100644
--- a/boost/asio/posix/stream_descriptor_service.hpp
+++ b/boost/asio/posix/stream_descriptor_service.hpp
@@ -2,7 +2,7 @@
// posix/stream_descriptor_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/raw_socket_service.hpp b/boost/asio/raw_socket_service.hpp
index 37040956be..06880d5abb 100644
--- a/boost/asio/raw_socket_service.hpp
+++ b/boost/asio/raw_socket_service.hpp
@@ -2,7 +2,7 @@
// raw_socket_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -118,17 +118,21 @@ public:
service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
}
+ // All socket services have access to each other's implementations.
+ template <typename Protocol1> friend class raw_socket_service;
+
/// Move-construct a new raw socket implementation from another protocol
/// type.
template <typename Protocol1>
void converting_move_construct(implementation_type& impl,
+ raw_socket_service<Protocol1>& other_service,
typename raw_socket_service<
Protocol1>::implementation_type& other_impl,
typename enable_if<is_convertible<
Protocol1, Protocol>::value>::type* = 0)
{
service_impl_.template converting_move_construct<Protocol1>(
- impl, other_impl);
+ impl, other_service.service_impl_, other_impl);
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
diff --git a/boost/asio/read.hpp b/boost/asio/read.hpp
index 6e0284011e..0db29b7831 100644
--- a/boost/asio/read.hpp
+++ b/boost/asio/read.hpp
@@ -2,7 +2,7 @@
// read.hpp
// ~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/read_at.hpp b/boost/asio/read_at.hpp
index 95628e602b..03f6c155c1 100644
--- a/boost/asio/read_at.hpp
+++ b/boost/asio/read_at.hpp
@@ -2,7 +2,7 @@
// read_at.hpp
// ~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/read_until.hpp b/boost/asio/read_until.hpp
index 833fbe700f..3ed288fc2c 100644
--- a/boost/asio/read_until.hpp
+++ b/boost/asio/read_until.hpp
@@ -2,7 +2,7 @@
// read_until.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/seq_packet_socket_service.hpp b/boost/asio/seq_packet_socket_service.hpp
index b48bbc4aab..fcccafe5ec 100644
--- a/boost/asio/seq_packet_socket_service.hpp
+++ b/boost/asio/seq_packet_socket_service.hpp
@@ -2,7 +2,7 @@
// seq_packet_socket_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -120,17 +120,21 @@ public:
service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
}
+ // All socket services have access to each other's implementations.
+ template <typename Protocol1> friend class seq_packet_socket_service;
+
/// Move-construct a new sequenced packet socket implementation from another
/// protocol type.
template <typename Protocol1>
void converting_move_construct(implementation_type& impl,
+ seq_packet_socket_service<Protocol1>& other_service,
typename seq_packet_socket_service<
Protocol1>::implementation_type& other_impl,
typename enable_if<is_convertible<
Protocol1, Protocol>::value>::type* = 0)
{
service_impl_.template converting_move_construct<Protocol1>(
- impl, other_impl);
+ impl, other_service.service_impl_, other_impl);
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
diff --git a/boost/asio/serial_port.hpp b/boost/asio/serial_port.hpp
index 6acac7181c..f3b6fb2450 100644
--- a/boost/asio/serial_port.hpp
+++ b/boost/asio/serial_port.hpp
@@ -2,7 +2,7 @@
// serial_port.hpp
// ~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/serial_port_base.hpp b/boost/asio/serial_port_base.hpp
index 36e454a1ab..884c7ba95d 100644
--- a/boost/asio/serial_port_base.hpp
+++ b/boost/asio/serial_port_base.hpp
@@ -2,7 +2,7 @@
// serial_port_base.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/serial_port_service.hpp b/boost/asio/serial_port_service.hpp
index 3e3812d28f..20cb288b1b 100644
--- a/boost/asio/serial_port_service.hpp
+++ b/boost/asio/serial_port_service.hpp
@@ -2,7 +2,7 @@
// serial_port_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/signal_set.hpp b/boost/asio/signal_set.hpp
index 18b5d4440b..422e4fca49 100644
--- a/boost/asio/signal_set.hpp
+++ b/boost/asio/signal_set.hpp
@@ -2,7 +2,7 @@
// signal_set.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/signal_set_service.hpp b/boost/asio/signal_set_service.hpp
index 107de75409..632eaf0aca 100644
--- a/boost/asio/signal_set_service.hpp
+++ b/boost/asio/signal_set_service.hpp
@@ -2,7 +2,7 @@
// signal_set_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/socket_acceptor_service.hpp b/boost/asio/socket_acceptor_service.hpp
index bcc9c46934..e00c76c901 100644
--- a/boost/asio/socket_acceptor_service.hpp
+++ b/boost/asio/socket_acceptor_service.hpp
@@ -2,7 +2,7 @@
// socket_acceptor_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -117,17 +117,21 @@ public:
service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
}
+ // All acceptor services have access to each other's implementations.
+ template <typename Protocol1> friend class socket_acceptor_service;
+
/// Move-construct a new socket acceptor implementation from another protocol
/// type.
template <typename Protocol1>
void converting_move_construct(implementation_type& impl,
+ socket_acceptor_service<Protocol1>& other_service,
typename socket_acceptor_service<
Protocol1>::implementation_type& other_impl,
typename enable_if<is_convertible<
Protocol1, Protocol>::value>::type* = 0)
{
service_impl_.template converting_move_construct<Protocol1>(
- impl, other_impl);
+ impl, other_service.service_impl_, other_impl);
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
diff --git a/boost/asio/socket_base.hpp b/boost/asio/socket_base.hpp
index 0d28351545..7adbf5abfd 100644
--- a/boost/asio/socket_base.hpp
+++ b/boost/asio/socket_base.hpp
@@ -2,7 +2,7 @@
// socket_base.hpp
// ~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/spawn.hpp b/boost/asio/spawn.hpp
index f37744235e..966bd3efcc 100644
--- a/boost/asio/spawn.hpp
+++ b/boost/asio/spawn.hpp
@@ -2,7 +2,7 @@
// spawn.hpp
// ~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl.hpp b/boost/asio/ssl.hpp
index 8e2a4fbe50..f82bdc043d 100644
--- a/boost/asio/ssl.hpp
+++ b/boost/asio/ssl.hpp
@@ -2,7 +2,7 @@
// ssl.hpp
// ~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/basic_context.hpp b/boost/asio/ssl/basic_context.hpp
index 7a0f727f42..734398bc29 100644
--- a/boost/asio/ssl/basic_context.hpp
+++ b/boost/asio/ssl/basic_context.hpp
@@ -2,7 +2,7 @@
// ssl/basic_context.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/context.hpp b/boost/asio/ssl/context.hpp
index 3cf2607737..8bab40ab3e 100644
--- a/boost/asio/ssl/context.hpp
+++ b/boost/asio/ssl/context.hpp
@@ -2,7 +2,7 @@
// ssl/context.hpp
// ~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/context_base.hpp b/boost/asio/ssl/context_base.hpp
index 6ee54cb457..1b5365bba1 100644
--- a/boost/asio/ssl/context_base.hpp
+++ b/boost/asio/ssl/context_base.hpp
@@ -2,7 +2,7 @@
// ssl/context_base.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -84,7 +84,16 @@ public:
tlsv12_client,
/// TLS version 1.2 server.
- tlsv12_server
+ tlsv12_server,
+
+ /// Generic TLS.
+ tls,
+
+ /// TLS client.
+ tls_client,
+
+ /// TLS server.
+ tls_server
};
/// Bitmask type for SSL options.
diff --git a/boost/asio/ssl/context_service.hpp b/boost/asio/ssl/context_service.hpp
index 098c403772..b0a31f3750 100644
--- a/boost/asio/ssl/context_service.hpp
+++ b/boost/asio/ssl/context_service.hpp
@@ -2,7 +2,7 @@
// ssl/context_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/detail/buffered_handshake_op.hpp b/boost/asio/ssl/detail/buffered_handshake_op.hpp
index bd0bc6aac1..b40fe5d69d 100644
--- a/boost/asio/ssl/detail/buffered_handshake_op.hpp
+++ b/boost/asio/ssl/detail/buffered_handshake_op.hpp
@@ -2,7 +2,7 @@
// ssl/detail/buffered_handshake_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/detail/engine.hpp b/boost/asio/ssl/detail/engine.hpp
index bd5b821d37..f31a4a7287 100644
--- a/boost/asio/ssl/detail/engine.hpp
+++ b/boost/asio/ssl/detail/engine.hpp
@@ -2,7 +2,7 @@
// ssl/detail/engine.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/detail/handshake_op.hpp b/boost/asio/ssl/detail/handshake_op.hpp
index 9e32965fec..dc61b702f0 100644
--- a/boost/asio/ssl/detail/handshake_op.hpp
+++ b/boost/asio/ssl/detail/handshake_op.hpp
@@ -2,7 +2,7 @@
// ssl/detail/handshake_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/detail/impl/engine.ipp b/boost/asio/ssl/detail/impl/engine.ipp
index f15f2e3800..f7d869c56d 100644
--- a/boost/asio/ssl/detail/impl/engine.ipp
+++ b/boost/asio/ssl/detail/impl/engine.ipp
@@ -2,7 +2,7 @@
// ssl/detail/impl/engine.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/detail/impl/openssl_init.ipp b/boost/asio/ssl/detail/impl/openssl_init.ipp
index 94b67f3792..725f5a75ee 100644
--- a/boost/asio/ssl/detail/impl/openssl_init.ipp
+++ b/boost/asio/ssl/detail/impl/openssl_init.ipp
@@ -3,7 +3,7 @@
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -36,11 +36,11 @@ class openssl_init_base::do_init
public:
do_init()
{
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
::SSL_library_init();
::SSL_load_error_strings();
::OpenSSL_add_all_algorithms();
-#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
mutexes_.resize(::CRYPTO_num_locks());
for (size_t i = 0; i < mutexes_.size(); ++i)
mutexes_[i].reset(new boost::asio::detail::mutex);
@@ -79,8 +79,9 @@ public:
#elif (OPENSSL_VERSION_NUMBER < 0x10100000L)
::ERR_remove_thread_state(NULL);
#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)
-#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) \
- && (OPENSSL_VERSION_NUMBER < 0x10100000L)
+#if !defined(SSL_OP_NO_COMPRESSION) \
+ && (OPENSSL_VERSION_NUMBER >= 0x10002000L) \
+ && (OPENSSL_VERSION_NUMBER < 0x10100000L)
::SSL_COMP_free_compression_methods();
#endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L)
// && (OPENSSL_VERSION_NUMBER < 0x10100000L)
diff --git a/boost/asio/ssl/detail/io.hpp b/boost/asio/ssl/detail/io.hpp
index 13494ad6b1..3dbe4520ef 100644
--- a/boost/asio/ssl/detail/io.hpp
+++ b/boost/asio/ssl/detail/io.hpp
@@ -2,7 +2,7 @@
// ssl/detail/io.hpp
// ~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/detail/openssl_init.hpp b/boost/asio/ssl/detail/openssl_init.hpp
index 447dbf628a..fd0432e589 100644
--- a/boost/asio/ssl/detail/openssl_init.hpp
+++ b/boost/asio/ssl/detail/openssl_init.hpp
@@ -2,7 +2,7 @@
// ssl/detail/openssl_init.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/detail/openssl_types.hpp b/boost/asio/ssl/detail/openssl_types.hpp
index d616d7a5f9..ca12943b7c 100644
--- a/boost/asio/ssl/detail/openssl_types.hpp
+++ b/boost/asio/ssl/detail/openssl_types.hpp
@@ -2,7 +2,7 @@
// ssl/detail/openssl_types.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -16,6 +16,7 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/socket_types.hpp>
#include <openssl/conf.h>
#include <openssl/ssl.h>
#if !defined(OPENSSL_NO_ENGINE)
@@ -25,6 +26,5 @@
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/x509v3.h>
-#include <boost/asio/detail/socket_types.hpp>
#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP
diff --git a/boost/asio/ssl/detail/password_callback.hpp b/boost/asio/ssl/detail/password_callback.hpp
index 07f1bd6058..5df01946ba 100644
--- a/boost/asio/ssl/detail/password_callback.hpp
+++ b/boost/asio/ssl/detail/password_callback.hpp
@@ -2,7 +2,7 @@
// ssl/detail/password_callback.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/detail/read_op.hpp b/boost/asio/ssl/detail/read_op.hpp
index 7708e8f0e7..f0b5d6ddf9 100644
--- a/boost/asio/ssl/detail/read_op.hpp
+++ b/boost/asio/ssl/detail/read_op.hpp
@@ -2,7 +2,7 @@
// ssl/detail/read_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/detail/shutdown_op.hpp b/boost/asio/ssl/detail/shutdown_op.hpp
index f9b20533c9..3a3f761c08 100644
--- a/boost/asio/ssl/detail/shutdown_op.hpp
+++ b/boost/asio/ssl/detail/shutdown_op.hpp
@@ -2,7 +2,7 @@
// ssl/detail/shutdown_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/detail/stream_core.hpp b/boost/asio/ssl/detail/stream_core.hpp
index a0a5aaf2d5..70d1feddbb 100644
--- a/boost/asio/ssl/detail/stream_core.hpp
+++ b/boost/asio/ssl/detail/stream_core.hpp
@@ -2,7 +2,7 @@
// ssl/detail/stream_core.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/detail/verify_callback.hpp b/boost/asio/ssl/detail/verify_callback.hpp
index 159c1da028..c4bea7c215 100644
--- a/boost/asio/ssl/detail/verify_callback.hpp
+++ b/boost/asio/ssl/detail/verify_callback.hpp
@@ -2,7 +2,7 @@
// ssl/detail/verify_callback.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/detail/write_op.hpp b/boost/asio/ssl/detail/write_op.hpp
index c9bf877930..c04eda86d2 100644
--- a/boost/asio/ssl/detail/write_op.hpp
+++ b/boost/asio/ssl/detail/write_op.hpp
@@ -2,7 +2,7 @@
// ssl/detail/write_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/error.hpp b/boost/asio/ssl/error.hpp
index 7f85fbd04f..968902c5d9 100644
--- a/boost/asio/ssl/error.hpp
+++ b/boost/asio/ssl/error.hpp
@@ -2,7 +2,7 @@
// ssl/error.hpp
// ~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -17,6 +17,7 @@
#include <boost/asio/detail/config.hpp>
#include <boost/system/error_code.hpp>
+#include <boost/asio/ssl/detail/openssl_types.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -32,7 +33,8 @@ enum ssl_errors
extern BOOST_ASIO_DECL
const boost::system::error_category& get_ssl_category();
-static const boost::system::error_category& ssl_category
+static const boost::system::error_category&
+ ssl_category BOOST_ASIO_UNUSED_VARIABLE
= boost::asio::error::get_ssl_category();
} // namespace error
@@ -54,7 +56,8 @@ enum stream_errors
extern BOOST_ASIO_DECL
const boost::system::error_category& get_stream_category();
-static const boost::system::error_category& stream_category
+static const boost::system::error_category&
+ stream_category BOOST_ASIO_UNUSED_VARIABLE
= boost::asio::ssl::error::get_stream_category();
} // namespace error
diff --git a/boost/asio/ssl/impl/context.hpp b/boost/asio/ssl/impl/context.hpp
index 797a9e1c78..52547d0437 100644
--- a/boost/asio/ssl/impl/context.hpp
+++ b/boost/asio/ssl/impl/context.hpp
@@ -3,7 +3,7 @@
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/impl/context.ipp b/boost/asio/ssl/impl/context.ipp
index aea2cbd528..a1fb9a578b 100644
--- a/boost/asio/ssl/impl/context.ipp
+++ b/boost/asio/ssl/impl/context.ipp
@@ -3,7 +3,7 @@
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -71,16 +71,15 @@ context::context(context::method m)
switch (m)
{
-#if defined(OPENSSL_NO_SSL2) \
- || (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+ // SSL v2.
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)
case context::sslv2:
case context::sslv2_client:
case context::sslv2_server:
boost::asio::detail::throw_error(
boost::asio::error::invalid_argument, "context");
break;
-#else // defined(OPENSSL_NO_SSL2)
- // || (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)
case context::sslv2:
handle_ = ::SSL_CTX_new(::SSLv2_method());
break;
@@ -90,9 +89,35 @@ context::context(context::method m)
case context::sslv2_server:
handle_ = ::SSL_CTX_new(::SSLv2_server_method());
break;
-#endif // defined(OPENSSL_NO_SSL2)
- // || (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-#if defined(OPENSSL_NO_SSL3)
+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)
+
+ // SSL v3.
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
+ case context::sslv3:
+ handle_ = ::SSL_CTX_new(::TLS_method());
+ if (handle_)
+ {
+ SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);
+ SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);
+ }
+ break;
+ case context::sslv3_client:
+ handle_ = ::SSL_CTX_new(::TLS_client_method());
+ if (handle_)
+ {
+ SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);
+ SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);
+ }
+ break;
+ case context::sslv3_server:
+ handle_ = ::SSL_CTX_new(::TLS_server_method());
+ if (handle_)
+ {
+ SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);
+ SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);
+ }
+ break;
+#elif defined(OPENSSL_NO_SSL3)
case context::sslv3:
case context::sslv3_client:
case context::sslv3_server:
@@ -110,7 +135,34 @@ context::context(context::method m)
handle_ = ::SSL_CTX_new(::SSLv3_server_method());
break;
#endif // defined(OPENSSL_NO_SSL3)
-#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
+
+ // TLS v1.0.
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
+ case context::tlsv1:
+ handle_ = ::SSL_CTX_new(::TLS_method());
+ if (handle_)
+ {
+ SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
+ SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);
+ }
+ break;
+ case context::tlsv1_client:
+ handle_ = ::SSL_CTX_new(::TLS_client_method());
+ if (handle_)
+ {
+ SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
+ SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);
+ }
+ break;
+ case context::tlsv1_server:
+ handle_ = ::SSL_CTX_new(::TLS_server_method());
+ if (handle_)
+ {
+ SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
+ SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);
+ }
+ break;
+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
case context::tlsv1:
handle_ = ::SSL_CTX_new(::TLSv1_method());
break;
@@ -120,18 +172,35 @@ context::context(context::method m)
case context::tlsv1_server:
handle_ = ::SSL_CTX_new(::TLSv1_server_method());
break;
-#endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)
- case context::sslv23:
- handle_ = ::SSL_CTX_new(::SSLv23_method());
+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+
+ // TLS v1.1.
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
+ case context::tlsv11:
+ handle_ = ::SSL_CTX_new(::TLS_method());
+ if (handle_)
+ {
+ SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
+ SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
+ }
break;
- case context::sslv23_client:
- handle_ = ::SSL_CTX_new(::SSLv23_client_method());
+ case context::tlsv11_client:
+ handle_ = ::SSL_CTX_new(::TLS_client_method());
+ if (handle_)
+ {
+ SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
+ SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
+ }
break;
- case context::sslv23_server:
- handle_ = ::SSL_CTX_new(::SSLv23_server_method());
+ case context::tlsv11_server:
+ handle_ = ::SSL_CTX_new(::TLS_server_method());
+ if (handle_)
+ {
+ SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);
+ SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);
+ }
break;
-#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
-#if defined(SSL_TXT_TLSV1_1)
+#elif defined(SSL_TXT_TLSV1_1)
case context::tlsv11:
handle_ = ::SSL_CTX_new(::TLSv1_1_method());
break;
@@ -149,7 +218,34 @@ context::context(context::method m)
boost::asio::error::invalid_argument, "context");
break;
#endif // defined(SSL_TXT_TLSV1_1)
-#if defined(SSL_TXT_TLSV1_2)
+
+ // TLS v1.2.
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
+ case context::tlsv12:
+ handle_ = ::SSL_CTX_new(::TLS_method());
+ if (handle_)
+ {
+ SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
+ SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
+ }
+ break;
+ case context::tlsv12_client:
+ handle_ = ::SSL_CTX_new(::TLS_client_method());
+ if (handle_)
+ {
+ SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
+ SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
+ }
+ break;
+ case context::tlsv12_server:
+ handle_ = ::SSL_CTX_new(::TLS_server_method());
+ if (handle_)
+ {
+ SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);
+ SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);
+ }
+ break;
+#elif defined(SSL_TXT_TLSV1_1)
case context::tlsv12:
handle_ = ::SSL_CTX_new(::TLSv1_2_method());
break;
@@ -159,31 +255,61 @@ context::context(context::method m)
case context::tlsv12_server:
handle_ = ::SSL_CTX_new(::TLSv1_2_server_method());
break;
-#else // defined(SSL_TXT_TLSV1_2)
+#else // defined(SSL_TXT_TLSV1_1)
case context::tlsv12:
case context::tlsv12_client:
case context::tlsv12_server:
boost::asio::detail::throw_error(
boost::asio::error::invalid_argument, "context");
break;
-#endif // defined(SSL_TXT_TLSV1_2)
-#else // (OPENSSL_VERSION_NUMBER < 0x10100000L)
- case context::tlsv1:
- case context::tlsv11:
- case context::tlsv12:
+#endif // defined(SSL_TXT_TLSV1_1)
+
+ // Any supported SSL/TLS version.
+ case context::sslv23:
+ handle_ = ::SSL_CTX_new(::SSLv23_method());
+ break;
+ case context::sslv23_client:
+ handle_ = ::SSL_CTX_new(::SSLv23_client_method());
+ break;
+ case context::sslv23_server:
+ handle_ = ::SSL_CTX_new(::SSLv23_server_method());
+ break;
+
+ // Any supported TLS version.
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
+ case context::tls:
handle_ = ::SSL_CTX_new(::TLS_method());
+ if (handle_)
+ SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
break;
- case context::tlsv1_client:
- case context::tlsv11_client:
- case context::tlsv12_client:
+ case context::tls_client:
handle_ = ::SSL_CTX_new(::TLS_client_method());
+ if (handle_)
+ SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
break;
- case context::tlsv1_server:
- case context::tlsv11_server:
- case context::tlsv12_server:
+ case context::tls_server:
handle_ = ::SSL_CTX_new(::TLS_server_method());
+ if (handle_)
+ SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);
+ break;
+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+ case context::tls:
+ handle_ = ::SSL_CTX_new(::SSLv23_method());
+ if (handle_)
+ SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
break;
-#endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)
+ case context::tls_client:
+ handle_ = ::SSL_CTX_new(::SSLv23_client_method());
+ if (handle_)
+ SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
+ break;
+ case context::tls_server:
+ handle_ = ::SSL_CTX_new(::SSLv23_server_method());
+ if (handle_)
+ SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
+ break;
+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+
default:
handle_ = ::SSL_CTX_new(0);
break;
@@ -228,7 +354,7 @@ context::~context()
{
if (handle_)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
void* cb_userdata = handle_->default_passwd_callback_userdata;
@@ -239,7 +365,7 @@ context::~context()
static_cast<detail::password_callback_base*>(
cb_userdata);
delete callback;
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
::SSL_CTX_set_default_passwd_cb_userdata(handle_, 0);
#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
handle_->default_passwd_callback_userdata = 0;
@@ -578,7 +704,7 @@ boost::system::error_code context::use_certificate_chain(
bio_cleanup bio = { make_buffer_bio(chain) };
if (bio.p)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
@@ -682,7 +808,7 @@ boost::system::error_code context::use_private_key(
{
::ERR_clear_error();
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
@@ -749,7 +875,7 @@ boost::system::error_code context::use_rsa_private_key(
{
::ERR_clear_error();
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);
void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
@@ -988,7 +1114,7 @@ int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
boost::system::error_code context::do_set_password_callback(
detail::password_callback_base* callback, boost::system::error_code& ec)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
void* old_callback = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);
::SSL_CTX_set_default_passwd_cb_userdata(handle_, callback);
#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)
diff --git a/boost/asio/ssl/impl/error.ipp b/boost/asio/ssl/impl/error.ipp
index e82afba615..bdbd836f3b 100644
--- a/boost/asio/ssl/impl/error.ipp
+++ b/boost/asio/ssl/impl/error.ipp
@@ -2,7 +2,7 @@
// ssl/impl/error.ipp
// ~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/impl/rfc2818_verification.ipp b/boost/asio/ssl/impl/rfc2818_verification.ipp
index 8b5ae3d2a8..7f22806735 100644
--- a/boost/asio/ssl/impl/rfc2818_verification.ipp
+++ b/boost/asio/ssl/impl/rfc2818_verification.ipp
@@ -2,7 +2,7 @@
// ssl/impl/rfc2818_verification.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/impl/src.hpp b/boost/asio/ssl/impl/src.hpp
index 63c0286711..942cc32308 100644
--- a/boost/asio/ssl/impl/src.hpp
+++ b/boost/asio/ssl/impl/src.hpp
@@ -2,7 +2,7 @@
// impl/ssl/src.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/old/basic_context.hpp b/boost/asio/ssl/old/basic_context.hpp
index 70643c315c..d8703b21ae 100644
--- a/boost/asio/ssl/old/basic_context.hpp
+++ b/boost/asio/ssl/old/basic_context.hpp
@@ -3,7 +3,7 @@
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/old/context_service.hpp b/boost/asio/ssl/old/context_service.hpp
index fd87f080b8..1d9fbc0751 100644
--- a/boost/asio/ssl/old/context_service.hpp
+++ b/boost/asio/ssl/old/context_service.hpp
@@ -3,7 +3,7 @@
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/old/detail/openssl_context_service.hpp b/boost/asio/ssl/old/detail/openssl_context_service.hpp
index e88eedff89..dd54c3297b 100644
--- a/boost/asio/ssl/old/detail/openssl_context_service.hpp
+++ b/boost/asio/ssl/old/detail/openssl_context_service.hpp
@@ -3,7 +3,7 @@
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/old/detail/openssl_stream_service.hpp b/boost/asio/ssl/old/detail/openssl_stream_service.hpp
index 1cf4fcb982..afccf3652a 100644
--- a/boost/asio/ssl/old/detail/openssl_stream_service.hpp
+++ b/boost/asio/ssl/old/detail/openssl_stream_service.hpp
@@ -3,7 +3,7 @@
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/old/stream.hpp b/boost/asio/ssl/old/stream.hpp
index d5defa6c23..a8c570ee08 100644
--- a/boost/asio/ssl/old/stream.hpp
+++ b/boost/asio/ssl/old/stream.hpp
@@ -3,7 +3,7 @@
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/old/stream_service.hpp b/boost/asio/ssl/old/stream_service.hpp
index 684d529d35..282687c2ea 100644
--- a/boost/asio/ssl/old/stream_service.hpp
+++ b/boost/asio/ssl/old/stream_service.hpp
@@ -3,7 +3,7 @@
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/rfc2818_verification.hpp b/boost/asio/ssl/rfc2818_verification.hpp
index 837cdfdbd0..21b0bca317 100644
--- a/boost/asio/ssl/rfc2818_verification.hpp
+++ b/boost/asio/ssl/rfc2818_verification.hpp
@@ -2,7 +2,7 @@
// ssl/rfc2818_verification.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/stream.hpp b/boost/asio/ssl/stream.hpp
index 02c5f66fca..1b883d3245 100644
--- a/boost/asio/ssl/stream.hpp
+++ b/boost/asio/ssl/stream.hpp
@@ -2,7 +2,7 @@
// ssl/stream.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/stream_base.hpp b/boost/asio/ssl/stream_base.hpp
index 41c77f0368..54404ca4b0 100644
--- a/boost/asio/ssl/stream_base.hpp
+++ b/boost/asio/ssl/stream_base.hpp
@@ -2,7 +2,7 @@
// ssl/stream_base.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/stream_service.hpp b/boost/asio/ssl/stream_service.hpp
index 8dc6a7bcfc..39e39f539c 100644
--- a/boost/asio/ssl/stream_service.hpp
+++ b/boost/asio/ssl/stream_service.hpp
@@ -2,7 +2,7 @@
// ssl/stream_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/verify_context.hpp b/boost/asio/ssl/verify_context.hpp
index fd4bc97c26..6b7a884e77 100644
--- a/boost/asio/ssl/verify_context.hpp
+++ b/boost/asio/ssl/verify_context.hpp
@@ -2,7 +2,7 @@
// ssl/verify_context.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/ssl/verify_mode.hpp b/boost/asio/ssl/verify_mode.hpp
index bb1a42274b..d63be08c9c 100644
--- a/boost/asio/ssl/verify_mode.hpp
+++ b/boost/asio/ssl/verify_mode.hpp
@@ -2,7 +2,7 @@
// ssl/verify_mode.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/steady_timer.hpp b/boost/asio/steady_timer.hpp
index 5fb512e259..f18ce399ae 100644
--- a/boost/asio/steady_timer.hpp
+++ b/boost/asio/steady_timer.hpp
@@ -2,7 +2,7 @@
// steady_timer.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/strand.hpp b/boost/asio/strand.hpp
index 72f8f30d2b..a4f3797e6a 100644
--- a/boost/asio/strand.hpp
+++ b/boost/asio/strand.hpp
@@ -2,7 +2,7 @@
// strand.hpp
// ~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/stream_socket_service.hpp b/boost/asio/stream_socket_service.hpp
index 3c6f470af3..09463f4718 100644
--- a/boost/asio/stream_socket_service.hpp
+++ b/boost/asio/stream_socket_service.hpp
@@ -2,7 +2,7 @@
// stream_socket_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -118,17 +118,21 @@ public:
service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
}
+ // All socket services have access to each other's implementations.
+ template <typename Protocol1> friend class stream_socket_service;
+
/// Move-construct a new stream socket implementation from another protocol
/// type.
template <typename Protocol1>
void converting_move_construct(implementation_type& impl,
+ stream_socket_service<Protocol1>& other_service,
typename stream_socket_service<
Protocol1>::implementation_type& other_impl,
typename enable_if<is_convertible<
Protocol1, Protocol>::value>::type* = 0)
{
service_impl_.template converting_move_construct<Protocol1>(
- impl, other_impl);
+ impl, other_service.service_impl_, other_impl);
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
diff --git a/boost/asio/streambuf.hpp b/boost/asio/streambuf.hpp
index e4037d4a09..de11184892 100644
--- a/boost/asio/streambuf.hpp
+++ b/boost/asio/streambuf.hpp
@@ -2,7 +2,7 @@
// streambuf.hpp
// ~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/system_timer.hpp b/boost/asio/system_timer.hpp
index 3bd9416b04..e95370dbbc 100644
--- a/boost/asio/system_timer.hpp
+++ b/boost/asio/system_timer.hpp
@@ -2,7 +2,7 @@
// system_timer.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/time_traits.hpp b/boost/asio/time_traits.hpp
index 35e701942c..feab4e1a72 100644
--- a/boost/asio/time_traits.hpp
+++ b/boost/asio/time_traits.hpp
@@ -2,7 +2,7 @@
// time_traits.hpp
// ~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/unyield.hpp b/boost/asio/unyield.hpp
index ccbb043547..37539810de 100644
--- a/boost/asio/unyield.hpp
+++ b/boost/asio/unyield.hpp
@@ -2,7 +2,7 @@
// unyield.hpp
// ~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/use_future.hpp b/boost/asio/use_future.hpp
index d0ef0edfde..43f6102e4d 100644
--- a/boost/asio/use_future.hpp
+++ b/boost/asio/use_future.hpp
@@ -2,7 +2,7 @@
// use_future.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/version.hpp b/boost/asio/version.hpp
index a8e546e611..7dfc1c3d18 100644
--- a/boost/asio/version.hpp
+++ b/boost/asio/version.hpp
@@ -2,7 +2,7 @@
// version.hpp
// ~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -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 101008 // 1.10.8
+#define BOOST_ASIO_VERSION 101009 // 1.10.9
#endif // BOOST_ASIO_VERSION_HPP
diff --git a/boost/asio/wait_traits.hpp b/boost/asio/wait_traits.hpp
index 806cf18435..f1a3c18243 100644
--- a/boost/asio/wait_traits.hpp
+++ b/boost/asio/wait_traits.hpp
@@ -2,7 +2,7 @@
// wait_traits.hpp
// ~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/waitable_timer_service.hpp b/boost/asio/waitable_timer_service.hpp
index 913a45b837..139d124ec5 100644
--- a/boost/asio/waitable_timer_service.hpp
+++ b/boost/asio/waitable_timer_service.hpp
@@ -2,7 +2,7 @@
// waitable_timer_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/windows/basic_handle.hpp b/boost/asio/windows/basic_handle.hpp
index 17895e62c3..6f903fd454 100644
--- a/boost/asio/windows/basic_handle.hpp
+++ b/boost/asio/windows/basic_handle.hpp
@@ -2,7 +2,7 @@
// windows/basic_handle.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/windows/basic_object_handle.hpp b/boost/asio/windows/basic_object_handle.hpp
index 7d3672d7e2..c82c2a7039 100644
--- a/boost/asio/windows/basic_object_handle.hpp
+++ b/boost/asio/windows/basic_object_handle.hpp
@@ -2,7 +2,7 @@
// windows/basic_object_handle.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2011 Boris Schaeling (boris@highscore.de)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/windows/basic_random_access_handle.hpp b/boost/asio/windows/basic_random_access_handle.hpp
index c1410be117..0d4184fb64 100644
--- a/boost/asio/windows/basic_random_access_handle.hpp
+++ b/boost/asio/windows/basic_random_access_handle.hpp
@@ -2,7 +2,7 @@
// windows/basic_random_access_handle.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/windows/basic_stream_handle.hpp b/boost/asio/windows/basic_stream_handle.hpp
index 9e34c86c6f..1b954fffbd 100644
--- a/boost/asio/windows/basic_stream_handle.hpp
+++ b/boost/asio/windows/basic_stream_handle.hpp
@@ -2,7 +2,7 @@
// windows/basic_stream_handle.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/windows/object_handle.hpp b/boost/asio/windows/object_handle.hpp
index 38d80543a1..614cc6bf3e 100644
--- a/boost/asio/windows/object_handle.hpp
+++ b/boost/asio/windows/object_handle.hpp
@@ -2,7 +2,7 @@
// windows/object_handle.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2011 Boris Schaeling (boris@highscore.de)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/windows/object_handle_service.hpp b/boost/asio/windows/object_handle_service.hpp
index e3207ad6ba..26ef6ed507 100644
--- a/boost/asio/windows/object_handle_service.hpp
+++ b/boost/asio/windows/object_handle_service.hpp
@@ -2,7 +2,7 @@
// windows/object_handle_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2011 Boris Schaeling (boris@highscore.de)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/windows/overlapped_ptr.hpp b/boost/asio/windows/overlapped_ptr.hpp
index 87d75d5adf..fa9fb3d200 100644
--- a/boost/asio/windows/overlapped_ptr.hpp
+++ b/boost/asio/windows/overlapped_ptr.hpp
@@ -2,7 +2,7 @@
// windows/overlapped_ptr.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/windows/random_access_handle.hpp b/boost/asio/windows/random_access_handle.hpp
index c65f60b756..993e193278 100644
--- a/boost/asio/windows/random_access_handle.hpp
+++ b/boost/asio/windows/random_access_handle.hpp
@@ -2,7 +2,7 @@
// windows/random_access_handle.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/windows/random_access_handle_service.hpp b/boost/asio/windows/random_access_handle_service.hpp
index 07fc2367ce..15a808f69a 100644
--- a/boost/asio/windows/random_access_handle_service.hpp
+++ b/boost/asio/windows/random_access_handle_service.hpp
@@ -2,7 +2,7 @@
// windows/random_access_handle_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/windows/stream_handle.hpp b/boost/asio/windows/stream_handle.hpp
index 5d4bb067b8..e52b8a16a6 100644
--- a/boost/asio/windows/stream_handle.hpp
+++ b/boost/asio/windows/stream_handle.hpp
@@ -2,7 +2,7 @@
// windows/stream_handle.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/windows/stream_handle_service.hpp b/boost/asio/windows/stream_handle_service.hpp
index 33ddd3dc37..5adcfaed1b 100644
--- a/boost/asio/windows/stream_handle_service.hpp
+++ b/boost/asio/windows/stream_handle_service.hpp
@@ -2,7 +2,7 @@
// windows/stream_handle_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/write.hpp b/boost/asio/write.hpp
index 39ab773ff1..b70e6f5bf5 100644
--- a/boost/asio/write.hpp
+++ b/boost/asio/write.hpp
@@ -2,7 +2,7 @@
// write.hpp
// ~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/write_at.hpp b/boost/asio/write_at.hpp
index ce7db694bf..266fc5bcaf 100644
--- a/boost/asio/write_at.hpp
+++ b/boost/asio/write_at.hpp
@@ -2,7 +2,7 @@
// write_at.hpp
// ~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/yield.hpp b/boost/asio/yield.hpp
index fc54d23b8e..85f71c7b8f 100644
--- a/boost/asio/yield.hpp
+++ b/boost/asio/yield.hpp
@@ -2,7 +2,7 @@
// yield.hpp
// ~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/atomic/detail/bitwise_cast.hpp b/boost/atomic/detail/bitwise_cast.hpp
index 8654d10b95..1405a25d6a 100644
--- a/boost/atomic/detail/bitwise_cast.hpp
+++ b/boost/atomic/detail/bitwise_cast.hpp
@@ -29,6 +29,17 @@ namespace boost {
namespace atomics {
namespace detail {
+template< typename T >
+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
+ // 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)));
+}
+
template< typename To, typename From >
BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT
{
@@ -39,8 +50,8 @@ BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT
value = {};
BOOST_ATOMIC_DETAIL_MEMCPY
(
- &reinterpret_cast< char& >(value.to),
- &reinterpret_cast< const char& >(from),
+ atomics::detail::addressof(value.to),
+ atomics::detail::addressof(from),
(sizeof(From) < sizeof(To) ? sizeof(From) : sizeof(To))
);
return value.to;
diff --git a/boost/atomic/detail/interlocked.hpp b/boost/atomic/detail/interlocked.hpp
index 1c62396bf5..82b6d3a0dc 100644
--- a/boost/atomic/detail/interlocked.hpp
+++ b/boost/atomic/detail/interlocked.hpp
@@ -169,7 +169,7 @@ extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
#endif
-#if _MSC_VER >= 1700 && defined(_M_ARM)
+#if _MSC_VER >= 1700 && (defined(_M_ARM) || defined(_M_ARM64))
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedExchangeAdd64)
@@ -251,10 +251,17 @@ extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_ACQUIRE(dest, addend) _InterlockedExchangeAdd64_acq((__int64*)(dest), (__int64)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELEASE(dest, addend) _InterlockedExchangeAdd64_rel((__int64*)(dest), (__int64)(addend))
+#if defined(_M_ARM64)
+#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64((__int64*)(dest), byte_offset))
+#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_RELAXED(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELAXED((__int64*)(dest), byte_offset))
+#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_ACQUIRE(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_ACQUIRE((__int64*)(dest), byte_offset))
+#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_RELEASE(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELEASE((__int64*)(dest), byte_offset))
+#else
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD((long*)(dest), byte_offset))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_RELAXED(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELAXED((long*)(dest), byte_offset))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_ACQUIRE(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_ACQUIRE((long*)(dest), byte_offset))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_RELEASE(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELEASE((long*)(dest), byte_offset))
+#endif
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedExchange8_nf)
diff --git a/boost/atomic/detail/ops_gcc_x86_dcas.hpp b/boost/atomic/detail/ops_gcc_x86_dcas.hpp
index 2f51182e5a..e356e8cfbd 100644
--- a/boost/atomic/detail/ops_gcc_x86_dcas.hpp
+++ b/boost/atomic/detail/ops_gcc_x86_dcas.hpp
@@ -73,6 +73,7 @@ struct gcc_dcas_x86
{
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
#if defined(__PIC__)
+ uint32_t v_lo = (uint32_t)v;
uint32_t scratch;
__asm__ __volatile__
(
@@ -84,8 +85,8 @@ struct gcc_dcas_x86
"1: lock; cmpxchg8b %[dest]\n\t"
"jne 1b\n\t"
"movl %[scratch], %%ebx\n\t"
- : [scratch] "=m" (scratch), [dest] "=o" (storage)
- : [value_lo] "a" ((uint32_t)v), "c" ((uint32_t)(v >> 32))
+ : [scratch] "=m" (scratch), [dest] "=o" (storage), [value_lo] "+a" (v_lo)
+ : "c" ((uint32_t)(v >> 32))
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "edx", "memory"
);
#else // defined(__PIC__)
@@ -103,6 +104,7 @@ struct gcc_dcas_x86
#endif // defined(__PIC__)
#else // !defined(BOOST_ATOMIC_DETAIL_NO_ASM_IMPLIED_ZERO_DISPLACEMENTS)
#if defined(__PIC__)
+ uint32_t v_lo = (uint32_t)v;
uint32_t scratch;
__asm__ __volatile__
(
@@ -115,11 +117,11 @@ struct gcc_dcas_x86
"jne 1b\n\t"
"movl %[scratch], %%ebx\n\t"
#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_CONSTRAINT_ALTERNATIVES)
- : [scratch] "=m,m" (scratch)
- : [value_lo] "a,a" ((uint32_t)v), "c,c" ((uint32_t)(v >> 32)), [dest] "D,S" (&storage)
+ : [scratch] "=m,m" (scratch), [value_lo] "+a,a" (v_lo)
+ : "c,c" ((uint32_t)(v >> 32)), [dest] "D,S" (&storage)
#else
- : [scratch] "=m" (scratch)
- : [value_lo] "a" ((uint32_t)v), "c" ((uint32_t)(v >> 32)), [dest] "D" (&storage)
+ : [scratch] "=m" (scratch), [value_lo] "+a" (v_lo)
+ : "c" ((uint32_t)(v >> 32)), [dest] "D" (&storage)
#endif
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "edx", "memory"
);
diff --git a/boost/atomic/detail/platform.hpp b/boost/atomic/detail/platform.hpp
index 34be8e6a0a..cc3cf1b67a 100644
--- a/boost/atomic/detail/platform.hpp
+++ b/boost/atomic/detail/platform.hpp
@@ -88,7 +88,7 @@
#define BOOST_ATOMIC_DETAIL_PLATFORM msvc_x86
-#elif defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
+#elif defined(_MSC_VER) && _MSC_VER >= 1700 && (defined(_M_ARM) || defined(_M_ARM64))
#define BOOST_ATOMIC_DETAIL_PLATFORM msvc_arm
diff --git a/boost/cerrno.hpp b/boost/cerrno.hpp
index 6f2669846d..57278f5cee 100644
--- a/boost/cerrno.hpp
+++ b/boost/cerrno.hpp
@@ -7,8 +7,8 @@
// See library home page at http://www.boost.org/libs/system
-#ifndef BOOST_CERRNO_HPP
-#define BOOST_CERRNO_HPP
+#ifndef BOOST_SYSTEM_CERRNO_HPP
+#define BOOST_SYSTEM_CERRNO_HPP
#include <cerrno>
diff --git a/boost/config/auto_link.hpp b/boost/config/auto_link.hpp
index 56a16b0b38..c71e8035dd 100644
--- a/boost/config/auto_link.hpp
+++ b/boost/config/auto_link.hpp
@@ -161,10 +161,15 @@ BOOST_LIB_VERSION: The Boost version, in the form x_y, for Boost version x.y.
// vc12:
# define BOOST_LIB_TOOLSET "vc120"
-# elif defined(BOOST_MSVC)
+# elif defined(BOOST_MSVC) && (BOOST_MSVC < 1910)
- // vc14:
-# define BOOST_LIB_TOOLSET "vc140"
+ // vc14:
+# define BOOST_LIB_TOOLSET "vc140"
+
+# elif defined(BOOST_MSVC)
+
+ // vc14.1:
+# define BOOST_LIB_TOOLSET "vc141"
# elif defined(__BORLANDC__)
diff --git a/boost/config/compiler/borland.hpp b/boost/config/compiler/borland.hpp
index ccd930ea53..b749496e38 100644
--- a/boost/config/compiler/borland.hpp
+++ b/boost/config/compiler/borland.hpp
@@ -185,6 +185,7 @@
#define BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_NO_CXX11_SCOPED_ENUMS
#define BOOST_NO_SFINAE_EXPR
+#define BOOST_NO_CXX11_SFINAE_EXPR
#define BOOST_NO_CXX11_TEMPLATE_ALIASES
#define BOOST_NO_CXX11_UNICODE_LITERALS // UTF-8 still not supported
#define BOOST_NO_CXX11_VARIADIC_TEMPLATES
diff --git a/boost/config/compiler/clang.hpp b/boost/config/compiler/clang.hpp
index 150e3c0d52..175229c64a 100644
--- a/boost/config/compiler/clang.hpp
+++ b/boost/config/compiler/clang.hpp
@@ -57,7 +57,7 @@
#define BOOST_HAS_NRVO
// Branch prediction hints
-#if defined(__has_builtin)
+#if !defined (__c2__) && defined(__has_builtin)
#if __has_builtin(__builtin_expect)
#define BOOST_LIKELY(x) __builtin_expect(x, 1)
#define BOOST_UNLIKELY(x) __builtin_expect(x, 0)
@@ -282,6 +282,10 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
+#if __cplusplus < 201103L
+#define BOOST_NO_CXX11_SFINAE_EXPR
+#endif
+
#if __cplusplus < 201400
// All versions with __cplusplus above this value seem to support this:
# define BOOST_NO_CXX14_DIGIT_SEPARATORS
diff --git a/boost/config/compiler/codegear.hpp b/boost/config/compiler/codegear.hpp
index e2f6061b37..3c5262fe49 100644
--- a/boost/config/compiler/codegear.hpp
+++ b/boost/config/compiler/codegear.hpp
@@ -112,6 +112,7 @@
#define BOOST_NO_CXX11_RAW_LITERALS
#define BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_NO_SFINAE_EXPR
+#define BOOST_NO_CXX11_SFINAE_EXPR
#define BOOST_NO_CXX11_TEMPLATE_ALIASES
#define BOOST_NO_CXX11_UNICODE_LITERALS
#define BOOST_NO_CXX11_VARIADIC_TEMPLATES
diff --git a/boost/config/compiler/common_edg.hpp b/boost/config/compiler/common_edg.hpp
index c09faeb0dd..eab9378486 100644
--- a/boost/config/compiler/common_edg.hpp
+++ b/boost/config/compiler/common_edg.hpp
@@ -95,6 +95,7 @@
#define BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_NO_CXX11_SCOPED_ENUMS
#define BOOST_NO_SFINAE_EXPR
+#define BOOST_NO_CXX11_SFINAE_EXPR
#define BOOST_NO_CXX11_STATIC_ASSERT
#define BOOST_NO_CXX11_TEMPLATE_ALIASES
#define BOOST_NO_CXX11_UNICODE_LITERALS
diff --git a/boost/config/compiler/cray.hpp b/boost/config/compiler/cray.hpp
index 837f815234..eab5287751 100644
--- a/boost/config/compiler/cray.hpp
+++ b/boost/config/compiler/cray.hpp
@@ -39,6 +39,7 @@
#define BOOST_NO_CXX11_TEMPLATE_ALIASES
#define BOOST_NO_CXX11_STATIC_ASSERT
#define BOOST_NO_SFINAE_EXPR
+#define BOOST_NO_CXX11_SFINAE_EXPR
#define BOOST_NO_CXX11_SCOPED_ENUMS
#define BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_NO_CXX11_RANGE_BASED_FOR
diff --git a/boost/config/compiler/digitalmars.hpp b/boost/config/compiler/digitalmars.hpp
index c344aae044..e371a68e99 100644
--- a/boost/config/compiler/digitalmars.hpp
+++ b/boost/config/compiler/digitalmars.hpp
@@ -71,6 +71,7 @@
#define BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_NO_CXX11_SCOPED_ENUMS
#define BOOST_NO_SFINAE_EXPR
+#define BOOST_NO_CXX11_SFINAE_EXPR
#define BOOST_NO_CXX11_STATIC_ASSERT
#define BOOST_NO_CXX11_TEMPLATE_ALIASES
#define BOOST_NO_CXX11_UNICODE_LITERALS
diff --git a/boost/config/compiler/gcc.hpp b/boost/config/compiler/gcc.hpp
index e319d04958..c82cbc7eda 100644
--- a/boost/config/compiler/gcc.hpp
+++ b/boost/config/compiler/gcc.hpp
@@ -253,6 +253,7 @@
#if (BOOST_GCC_VERSION < 40800) || !defined(BOOST_GCC_CXX11)
# define BOOST_NO_CXX11_ALIGNAS
# define BOOST_NO_CXX11_THREAD_LOCAL
+# define BOOST_NO_CXX11_SFINAE_EXPR
#endif
// C++0x features in 4.8.1 and later
diff --git a/boost/config/compiler/gcc_xml.hpp b/boost/config/compiler/gcc_xml.hpp
index b56c78628c..63b08ac483 100644
--- a/boost/config/compiler/gcc_xml.hpp
+++ b/boost/config/compiler/gcc_xml.hpp
@@ -46,6 +46,7 @@
# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
# define BOOST_NO_CXX11_SCOPED_ENUMS
# define BOOST_NO_SFINAE_EXPR
+# define BOOST_NO_CXX11_SFINAE_EXPR
# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
# define BOOST_NO_CXX11_LAMBDAS
# define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS
diff --git a/boost/config/compiler/hp_acc.hpp b/boost/config/compiler/hp_acc.hpp
index a773b8c442..9df18eaf67 100644
--- a/boost/config/compiler/hp_acc.hpp
+++ b/boost/config/compiler/hp_acc.hpp
@@ -114,6 +114,7 @@
#define BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_NO_CXX11_SCOPED_ENUMS
#define BOOST_NO_SFINAE_EXPR
+#define BOOST_NO_CXX11_SFINAE_EXPR
#define BOOST_NO_CXX11_STATIC_ASSERT
#define BOOST_NO_CXX11_TEMPLATE_ALIASES
#define BOOST_NO_CXX11_UNICODE_LITERALS
diff --git a/boost/config/compiler/intel.hpp b/boost/config/compiler/intel.hpp
index 1885ea281f..f55189a0ab 100644
--- a/boost/config/compiler/intel.hpp
+++ b/boost/config/compiler/intel.hpp
@@ -39,15 +39,20 @@
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#endif
-#else
+#else // defined(_MSC_VER)
#include <boost/config/compiler/gcc.hpp>
#undef BOOST_GCC_VERSION
#undef BOOST_GCC_CXX11
+// Broken in all versions up to 17 (newer versions not tested)
+#if (__INTEL_COMPILER <= 1700) && !defined(BOOST_NO_CXX14_CONSTEXPR)
+# define BOOST_NO_CXX14_CONSTEXPR
#endif
+#endif // defined(_MSC_VER)
+
#undef BOOST_COMPILER
#if defined(__INTEL_COMPILER)
@@ -92,7 +97,7 @@
# define BOOST_INTEL_LINUX BOOST_INTEL
#endif
-#else
+#else // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500) && (defined(_MSC_VER) || defined(__GNUC__))
#include <boost/config/compiler/common_edg.hpp>
@@ -410,6 +415,11 @@ template<> struct assert_intrinsic_wchar_t<unsigned short> {};
# undef BOOST_NO_SFINAE_EXPR
#endif
+// BOOST_NO_CXX11_SFINAE_EXPR
+#if (BOOST_INTEL_CXX_VERSION >= 1500) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40800)) && !defined(_MSC_VER)
+# undef BOOST_NO_CXX11_SFINAE_EXPR
+#endif
+
// BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
#if (BOOST_INTEL_CXX_VERSION >= 1500) && (!defined(BOOST_INTEL_GCC_VERSION) || (BOOST_INTEL_GCC_VERSION >= 40500)) && (!defined(_MSC_VER) || (_MSC_FULL_VER >= 180020827))
// This is available in earlier Intel releases, but breaks Multiprecision:
@@ -483,7 +493,7 @@ template<> struct assert_intrinsic_wchar_t<unsigned short> {};
# undef BOOST_NO_CXX11_FINAL
#endif
-#endif
+#endif // defined(BOOST_INTEL_STDCXX0X)
//
// Broken in all versions up to 15:
@@ -500,11 +510,6 @@ template<> struct assert_intrinsic_wchar_t<unsigned short> {};
# define BOOST_NO_CXX11_HDR_TUPLE
#endif
-// Broken in all versions up to 17:
-#if !defined(BOOST_NO_CXX14_CONSTEXPR)
-#define BOOST_NO_CXX14_CONSTEXPR
-#endif
-
#if (BOOST_INTEL_CXX_VERSION < 1200)
//
// fenv.h appears not to work with Intel prior to 12.0:
@@ -535,10 +540,10 @@ template<> struct assert_intrinsic_wchar_t<unsigned short> {};
# define BOOST_HAS_INT128
#endif
-#endif
+#endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500) && (defined(_MSC_VER) || defined(__GNUC__))
//
// last known and checked version:
-#if (BOOST_INTEL_CXX_VERSION > 1500)
+#if (BOOST_INTEL_CXX_VERSION > 1700)
# if defined(BOOST_ASSERT_CONFIG)
# error "Unknown compiler version - please run the configure tests and report the results"
# elif defined(_MSC_VER)
diff --git a/boost/config/compiler/metrowerks.hpp b/boost/config/compiler/metrowerks.hpp
index 3c5e22868a..8d42563c34 100644
--- a/boost/config/compiler/metrowerks.hpp
+++ b/boost/config/compiler/metrowerks.hpp
@@ -113,6 +113,7 @@
#define BOOST_NO_CXX11_RAW_LITERALS
#define BOOST_NO_CXX11_SCOPED_ENUMS
#define BOOST_NO_SFINAE_EXPR
+#define BOOST_NO_CXX11_SFINAE_EXPR
#define BOOST_NO_CXX11_STATIC_ASSERT
#define BOOST_NO_CXX11_TEMPLATE_ALIASES
#define BOOST_NO_CXX11_UNICODE_LITERALS
diff --git a/boost/config/compiler/mpw.hpp b/boost/config/compiler/mpw.hpp
index 084f9e154f..1b8d39ea29 100644
--- a/boost/config/compiler/mpw.hpp
+++ b/boost/config/compiler/mpw.hpp
@@ -62,6 +62,7 @@
#define BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_NO_CXX11_SCOPED_ENUMS
#define BOOST_NO_SFINAE_EXPR
+#define BOOST_NO_CXX11_SFINAE_EXPR
#define BOOST_NO_CXX11_STATIC_ASSERT
#define BOOST_NO_CXX11_TEMPLATE_ALIASES
#define BOOST_NO_CXX11_UNICODE_LITERALS
diff --git a/boost/config/compiler/pathscale.hpp b/boost/config/compiler/pathscale.hpp
index a5e65af49b..016ad5a42f 100644
--- a/boost/config/compiler/pathscale.hpp
+++ b/boost/config/compiler/pathscale.hpp
@@ -37,6 +37,7 @@
# define BOOST_NO_CXX11_TEMPLATE_ALIASES
# define BOOST_NO_CXX11_STATIC_ASSERT
# define BOOST_NO_SFINAE_EXPR
+# define BOOST_NO_CXX11_SFINAE_EXPR
# define BOOST_NO_CXX11_SCOPED_ENUMS
# define BOOST_NO_CXX11_RVALUE_REFERENCES
# define BOOST_NO_CXX11_RANGE_BASED_FOR
diff --git a/boost/config/compiler/pgi.hpp b/boost/config/compiler/pgi.hpp
index fa2d5e402d..af7005142f 100644
--- a/boost/config/compiler/pgi.hpp
+++ b/boost/config/compiler/pgi.hpp
@@ -88,6 +88,7 @@
#define BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_NO_CXX11_SCOPED_ENUMS
#define BOOST_NO_SFINAE_EXPR
+#define BOOST_NO_CXX11_SFINAE_EXPR
#define BOOST_NO_CXX11_STATIC_ASSERT
#define BOOST_NO_SWPRINTF
#define BOOST_NO_CXX11_TEMPLATE_ALIASES
diff --git a/boost/config/compiler/sunpro_cc.hpp b/boost/config/compiler/sunpro_cc.hpp
index ac259fce28..cdd30b14ea 100644
--- a/boost/config/compiler/sunpro_cc.hpp
+++ b/boost/config/compiler/sunpro_cc.hpp
@@ -141,6 +141,7 @@
//
# define BOOST_HAS_LONG_LONG
+#define BOOST_NO_CXX11_SFINAE_EXPR
// C++ 14:
#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304)
diff --git a/boost/config/compiler/vacpp.hpp b/boost/config/compiler/vacpp.hpp
index 3fbed9fafe..b75a1bd144 100644
--- a/boost/config/compiler/vacpp.hpp
+++ b/boost/config/compiler/vacpp.hpp
@@ -114,6 +114,7 @@
# define BOOST_NO_CXX11_SCOPED_ENUMS
#endif
#define BOOST_NO_SFINAE_EXPR
+#define BOOST_NO_CXX11_SFINAE_EXPR
#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
#if ! __IBMCPP_STATIC_ASSERT
# define BOOST_NO_CXX11_STATIC_ASSERT
diff --git a/boost/config/compiler/visualc.hpp b/boost/config/compiler/visualc.hpp
index cdbc9b6701..760e2833f8 100644
--- a/boost/config/compiler/visualc.hpp
+++ b/boost/config/compiler/visualc.hpp
@@ -190,7 +190,7 @@
# define BOOST_NO_CXX11_CONSTEXPR
#endif
-// C++14 features supported by VC++ 15 Preview 5
+// C++14 features supported by VC++ 14.1 (Visual Studio 2017)
//
#if (_MSC_VER < 1910)
# define BOOST_NO_CXX14_AGGREGATE_NSDMI
@@ -217,6 +217,27 @@
// C++ 11:
//
#define BOOST_NO_TWO_PHASE_NAME_LOOKUP
+#define BOOST_NO_CXX11_SFINAE_EXPR
+
+//
+// Things that don't work in clr mode:
+//
+#ifdef _M_CEE
+#ifndef BOOST_NO_CXX11_THREAD_LOCAL
+# define BOOST_NO_CXX11_THREAD_LOCAL
+#endif
+#ifndef BOOST_NO_SFINAE_EXPR
+# define BOOST_NO_SFINAE_EXPR
+#endif
+#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
+# define BOOST_NO_CXX11_REF_QUALIFIERS
+#endif
+#endif
+#ifdef _M_CEE_PURE
+#ifndef BOOST_NO_CXX11_CONSTEXPR
+# define BOOST_NO_CXX11_CONSTEXPR
+#endif
+#endif
//
// prefix and suffix headers:
@@ -282,8 +303,10 @@
# define BOOST_COMPILER_VERSION 11.0
# elif _MSC_VER < 1900
# define BOOST_COMPILER_VERSION 12.0
-# elif _MSC_VER < 2000
+# elif _MSC_VER < 1910
# define BOOST_COMPILER_VERSION 14.0
+# elif _MSC_VER < 1920
+# define BOOST_COMPILER_VERSION 14.1
# else
# define BOOST_COMPILER_VERSION _MSC_VER
# endif
@@ -293,7 +316,7 @@
#endif
//
-// last known and checked version is 19.10.24629 (VC++ 2017 RC):
+// last known and checked version is 19.10.25017 (VC++ 2017):
#if (_MSC_VER > 1910)
# if defined(BOOST_ASSERT_CONFIG)
# error "Unknown compiler version - please run the configure tests and report the results"
diff --git a/boost/config/platform/cygwin.hpp b/boost/config/platform/cygwin.hpp
index b7ef572fa6..53e23f7f08 100644
--- a/boost/config/platform/cygwin.hpp
+++ b/boost/config/platform/cygwin.hpp
@@ -23,7 +23,7 @@
# define BOOST_HAS_SCHED_YIELD
# define BOOST_HAS_GETTIMEOFDAY
# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
-# define BOOST_HAS_SIGACTION
+//# define BOOST_HAS_SIGACTION
#else
# if !defined(BOOST_HAS_WINTHREADS)
# define BOOST_HAS_WINTHREADS
@@ -51,7 +51,6 @@
#ifdef BOOST_HAS_NL_TYPES_H
# undef BOOST_HAS_NL_TYPES_H
#endif
-
diff --git a/boost/config/stdlib/dinkumware.hpp b/boost/config/stdlib/dinkumware.hpp
index 8cf5d4dd26..3b95dcf3b5 100644
--- a/boost/config/stdlib/dinkumware.hpp
+++ b/boost/config/stdlib/dinkumware.hpp
@@ -196,6 +196,36 @@
# endif
#endif
+
+//
+// Things not supported by the CLR:
+#ifdef _M_CEE
+#ifndef BOOST_NO_CXX11_HDR_MUTEX
+# define BOOST_NO_CXX11_HDR_MUTEX
+#endif
+#ifndef BOOST_NO_CXX11_HDR_ATOMIC
+# define BOOST_NO_CXX11_HDR_ATOMIC
+#endif
+#ifndef BOOST_NO_CXX11_HDR_FUTURE
+# define BOOST_NO_CXX11_HDR_FUTURE
+#endif
+#ifndef BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
+# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
+#endif
+#ifndef BOOST_NO_CXX11_HDR_THREAD
+# define BOOST_NO_CXX11_HDR_THREAD
+#endif
+#ifndef BOOST_NO_CXX14_HDR_SHARED_MUTEX
+# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
+#endif
+#ifndef BOOST_NO_CXX14_STD_EXCHANGE
+# define BOOST_NO_CXX14_STD_EXCHANGE
+#endif
+#ifndef BOOST_NO_FENV_H
+# define BOOST_NO_FENV_H
+#endif
+#endif
+
#ifdef _CPPLIB_VER
# define BOOST_DINKUMWARE_STDLIB _CPPLIB_VER
#else
diff --git a/boost/config/stdlib/libstdcpp3.hpp b/boost/config/stdlib/libstdcpp3.hpp
index 557767b1fa..205489a920 100644
--- a/boost/config/stdlib/libstdcpp3.hpp
+++ b/boost/config/stdlib/libstdcpp3.hpp
@@ -101,8 +101,8 @@
//
// Decide which version of libstdc++ we have, normally
-// stdlibc++ C++0x support is detected via __GNUC__, __GNUC_MINOR__, and possibly
-// __GNUC_PATCHLEVEL__ at the suggestion of Jonathan Wakely, one of the stdlibc++
+// libstdc++ C++0x support is detected via __GNUC__, __GNUC_MINOR__, and possibly
+// __GNUC_PATCHLEVEL__ at the suggestion of Jonathan Wakely, one of the libstdc++
// developers. He also commented:
//
// "I'm not sure how useful __GLIBCXX__ is for your purposes, for instance in
@@ -110,7 +110,7 @@
// Although 4.3.0 was released earlier than 4.2.4, it has better C++0x support
// than any release in the 4.2 series."
//
-// Another resource for understanding stdlibc++ features is:
+// Another resource for understanding libstdc++ features is:
// http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#manual.intro.status.standard.200x
//
// However, using the GCC version number fails when the compiler is clang since this
@@ -222,7 +222,7 @@
//
#if (BOOST_LIBSTDCXX_VERSION < 40700) || !defined(BOOST_LIBSTDCXX11)
// Note that although <chrono> existed prior to 4.7, "steady_clock" is spelled "monotonic_clock"
-// so 4.7.0 is the first truely conforming one.
+// so 4.7.0 is the first truly conforming one.
# define BOOST_NO_CXX11_HDR_CHRONO
# define BOOST_NO_CXX11_ALLOCATOR
#endif
diff --git a/boost/config/suffix.hpp b/boost/config/suffix.hpp
index eeaec2bf69..6df9223fb2 100644
--- a/boost/config/suffix.hpp
+++ b/boost/config/suffix.hpp
@@ -583,6 +583,25 @@ namespace std{ using ::type_info; }
# define BOOST_GPU_ENABLED
# endif
+// BOOST_RESTRICT ---------------------------------------------//
+// Macro to use in place of 'restrict' keyword variants
+#if !defined(BOOST_RESTRICT)
+# if defined(_MSC_VER)
+# define BOOST_RESTRICT __restrict
+# if !defined(BOOST_NO_RESTRICT_REFERENCES) && (_MSC_FULL_VER < 190023026)
+# define BOOST_NO_RESTRICT_REFERENCES
+# endif
+# elif defined(__GNUC__) && __GNUC__ > 3
+ // Clang also defines __GNUC__ (as 4)
+# define BOOST_RESTRICT __restrict__
+# else
+# define BOOST_RESTRICT
+# if !defined(BOOST_NO_RESTRICT_REFERENCES)
+# define BOOST_NO_RESTRICT_REFERENCES
+# endif
+# endif
+#endif
+
// BOOST_FORCEINLINE ---------------------------------------------//
// Macro to use in place of 'inline' to force a function to be inline
#if !defined(BOOST_FORCEINLINE)
@@ -604,7 +623,7 @@ namespace std{ using ::type_info; }
# elif defined(__GNUC__) && __GNUC__ > 3
// Clang also defines __GNUC__ (as 4)
# if defined(__CUDACC__)
- // nvcc doesn't always parse __noinline__,
+ // nvcc doesn't always parse __noinline__,
// see: https://svn.boost.org/trac/boost/ticket/9392
# define BOOST_NOINLINE __attribute__ ((noinline))
# else
diff --git a/boost/container/allocator_traits.hpp b/boost/container/allocator_traits.hpp
index e6a882e594..d6621f614a 100644
--- a/boost/container/allocator_traits.hpp
+++ b/boost/container/allocator_traits.hpp
@@ -289,18 +289,18 @@ struct allocator_traits
//! <b>Returns</b>: <code>a.allocate(n)</code>
//!
- static pointer allocate(Allocator &a, size_type n)
+ BOOST_CONTAINER_FORCEINLINE static pointer allocate(Allocator &a, size_type n)
{ return a.allocate(n); }
//! <b>Returns</b>: <code>a.deallocate(p, n)</code>
//!
//! <b>Throws</b>: Nothing
- static void deallocate(Allocator &a, pointer p, size_type n)
+ BOOST_CONTAINER_FORCEINLINE static void deallocate(Allocator &a, pointer p, size_type n)
{ a.deallocate(p, n); }
//! <b>Effects</b>: calls <code>a.allocate(n, p)</code> if that call is well-formed;
//! otherwise, invokes <code>a.allocate(n)</code>
- static pointer allocate(Allocator &a, size_type n, const_void_pointer p)
+ BOOST_CONTAINER_FORCEINLINE static pointer allocate(Allocator &a, size_type n, const_void_pointer p)
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_allocate
@@ -312,7 +312,7 @@ struct allocator_traits
//! <b>Effects</b>: calls <code>a.destroy(p)</code> if that call is well-formed;
//! otherwise, invokes <code>p->~T()</code>.
template<class T>
- static void destroy(Allocator &a, T*p) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static void destroy(Allocator &a, T*p) BOOST_NOEXCEPT_OR_NOTHROW
{
typedef T* destroy_pointer;
const bool value = boost::container::container_detail::
@@ -324,7 +324,7 @@ struct allocator_traits
//! <b>Returns</b>: <code>a.max_size()</code> if that expression is well-formed; otherwise,
//! <code>numeric_limits<size_type>::max()</code>.
- static size_type max_size(const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static size_type max_size(const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
{
const bool value = allocator_traits_detail::has_max_size<Allocator, size_type (Allocator::*)() const>::value;
container_detail::bool_<value> flag;
@@ -333,7 +333,7 @@ struct allocator_traits
//! <b>Returns</b>: <code>a.select_on_container_copy_construction()</code> if that expression is well-formed;
//! otherwise, a.
- static BOOST_CONTAINER_DOC1ST(Allocator,
+ BOOST_CONTAINER_FORCEINLINE static BOOST_CONTAINER_DOC1ST(Allocator,
typename container_detail::if_c
< allocator_traits_detail::has_select_on_container_copy_construction<Allocator BOOST_MOVE_I Allocator (Allocator::*)() const>::value
BOOST_MOVE_I Allocator BOOST_MOVE_I const Allocator & >::type)
@@ -349,7 +349,7 @@ struct allocator_traits
//! <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>
template <class T, class ...Args>
- static void construct(Allocator & a, T* p, BOOST_FWD_REF(Args)... args)
+ BOOST_CONTAINER_FORCEINLINE static void construct(Allocator & a, T* p, BOOST_FWD_REF(Args)... args)
{
static const bool value = ::boost::move_detail::and_
< container_detail::is_not_std_allocator<Allocator>
@@ -363,7 +363,7 @@ struct allocator_traits
//! <b>Returns</b>: <code>a.storage_is_unpropagable(p)</code> if is_partially_propagable::value is true; otherwise,
//! <code>false</code>.
- static bool storage_is_unpropagable(const Allocator &a, pointer p) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static bool storage_is_unpropagable(const Allocator &a, pointer p) BOOST_NOEXCEPT_OR_NOTHROW
{
container_detail::bool_<is_partially_propagable::value> flag;
return allocator_traits::priv_storage_is_unpropagable(flag, a, p);
@@ -371,7 +371,7 @@ struct allocator_traits
//! <b>Returns</b>: <code>true</code> if <code>is_always_equal::value == true</code>, otherwise,
//! <code>a == b</code>.
- static bool equal(const Allocator &a, const Allocator &b) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static bool equal(const Allocator &a, const Allocator &b) BOOST_NOEXCEPT_OR_NOTHROW
{
container_detail::bool_<is_always_equal::value> flag;
return allocator_traits::priv_equal(flag, a, b);
@@ -379,46 +379,46 @@ struct allocator_traits
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
private:
- static pointer priv_allocate(container_detail::true_type, Allocator &a, size_type n, const_void_pointer p)
+ BOOST_CONTAINER_FORCEINLINE static pointer priv_allocate(container_detail::true_type, Allocator &a, size_type n, const_void_pointer p)
{ return a.allocate(n, p); }
- static pointer priv_allocate(container_detail::false_type, Allocator &a, size_type n, const_void_pointer)
+ BOOST_CONTAINER_FORCEINLINE static pointer priv_allocate(container_detail::false_type, Allocator &a, size_type n, const_void_pointer)
{ return a.allocate(n); }
template<class T>
- static void priv_destroy(container_detail::true_type, Allocator &a, T* p) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static void priv_destroy(container_detail::true_type, Allocator &a, T* p) BOOST_NOEXCEPT_OR_NOTHROW
{ a.destroy(p); }
template<class T>
- static void priv_destroy(container_detail::false_type, Allocator &, T* p) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static void priv_destroy(container_detail::false_type, Allocator &, T* p) BOOST_NOEXCEPT_OR_NOTHROW
{ p->~T(); (void)p; }
- static size_type priv_max_size(container_detail::true_type, const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static size_type priv_max_size(container_detail::true_type, const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
{ return a.max_size(); }
- static size_type priv_max_size(container_detail::false_type, const Allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static size_type priv_max_size(container_detail::false_type, const Allocator &) BOOST_NOEXCEPT_OR_NOTHROW
{ return size_type(-1)/sizeof(value_type); }
- static Allocator priv_select_on_container_copy_construction(container_detail::true_type, const Allocator &a)
+ BOOST_CONTAINER_FORCEINLINE static Allocator priv_select_on_container_copy_construction(container_detail::true_type, const Allocator &a)
{ return a.select_on_container_copy_construction(); }
- static const Allocator &priv_select_on_container_copy_construction(container_detail::false_type, const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static const Allocator &priv_select_on_container_copy_construction(container_detail::false_type, const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
{ return a; }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class ...Args>
- static void priv_construct(container_detail::true_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args)
+ BOOST_CONTAINER_FORCEINLINE static void priv_construct(container_detail::true_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args)
{ a.construct( p, ::boost::forward<Args>(args)...); }
template<class T, class ...Args>
- static void priv_construct(container_detail::false_type, Allocator &, T *p, BOOST_FWD_REF(Args) ...args)
+ BOOST_CONTAINER_FORCEINLINE static void priv_construct(container_detail::false_type, Allocator &, T *p, BOOST_FWD_REF(Args) ...args)
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward<Args>(args)...); }
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
public:
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL(N) \
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
- static void construct(Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE static void construct(Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
static const bool value = ::boost::move_detail::and_ \
< container_detail::is_not_std_allocator<Allocator> \
@@ -438,11 +438,11 @@ struct allocator_traits
/////////////////////////////////
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL(N) \
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
- static void priv_construct(container_detail::true_type, Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE static void priv_construct(container_detail::true_type, Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ a.construct( p BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); }\
\
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
- static void priv_construct(container_detail::false_type, Allocator &, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE static void priv_construct(container_detail::false_type, Allocator &, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ ::new((void*)p, boost_container_new_t()) T(BOOST_MOVE_FWD##N); }\
//
BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL)
@@ -451,19 +451,19 @@ struct allocator_traits
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T>
- static void priv_construct(container_detail::false_type, Allocator &, T *p, const ::boost::container::default_init_t&)
+ BOOST_CONTAINER_FORCEINLINE static void priv_construct(container_detail::false_type, Allocator &, T *p, const ::boost::container::default_init_t&)
{ ::new((void*)p, boost_container_new_t()) T; }
- static bool priv_storage_is_unpropagable(container_detail::true_type, const Allocator &a, pointer p)
+ BOOST_CONTAINER_FORCEINLINE static bool priv_storage_is_unpropagable(container_detail::true_type, const Allocator &a, pointer p)
{ return a.storage_is_unpropagable(p); }
- static bool priv_storage_is_unpropagable(container_detail::false_type, const Allocator &, pointer)
+ BOOST_CONTAINER_FORCEINLINE static bool priv_storage_is_unpropagable(container_detail::false_type, const Allocator &, pointer)
{ return false; }
- static bool priv_equal(container_detail::true_type, const Allocator &, const Allocator &)
+ BOOST_CONTAINER_FORCEINLINE static bool priv_equal(container_detail::true_type, const Allocator &, const Allocator &)
{ return true; }
- static bool priv_equal(container_detail::false_type, const Allocator &a, const Allocator &b)
+ BOOST_CONTAINER_FORCEINLINE static bool priv_equal(container_detail::false_type, const Allocator &a, const Allocator &b)
{ return a == b; }
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
diff --git a/boost/container/detail/advanced_insert_int.hpp b/boost/container/detail/advanced_insert_int.hpp
index 278cd1b3f1..1050857c46 100644
--- a/boost/container/detail/advanced_insert_int.hpp
+++ b/boost/container/detail/advanced_insert_int.hpp
@@ -107,8 +107,8 @@ struct insert_n_copies_proxy
void copy_n_and_update(Allocator &, Iterator p, size_type n) const
{
- for (; 0 < n; --n, ++p){
- *p = v_;
+ for (; 0 < n; --n, ++p){
+ *p = v_;
}
}
diff --git a/boost/container/detail/dispatch_uses_allocator.hpp b/boost/container/detail/dispatch_uses_allocator.hpp
index fdf203cef8..946fdf615b 100644
--- a/boost/container/detail/dispatch_uses_allocator.hpp
+++ b/boost/container/detail/dispatch_uses_allocator.hpp
@@ -287,7 +287,7 @@ template< typename ConstructAlloc, typename ArgAlloc, class Pair \
, template<class, class, class, class, class, class, class, class, class, class> class BoostTuple \
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 > \
typename container_detail::enable_if< container_detail::is_pair<Pair> >::type\
- dispatch_uses_allocator( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t\
+ dispatch_uses_allocator( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* 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)\
{\
@@ -313,7 +313,7 @@ BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BO
template< typename ConstructAlloc, typename ArgAlloc, class Pair
, template<class ...> class Tuple, class... Args1, class... Args2, size_t... Indexes1, size_t... Indexes2>
- void dispatch_uses_allocator_index( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair
+ void dispatch_uses_allocator_index( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair
, Tuple<Args1...>& t1, Tuple<Args2...>& t2, index_tuple<Indexes1...>, index_tuple<Indexes2...>)
{
(void)t1; (void)t2;
@@ -331,7 +331,7 @@ BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BO
template< typename ConstructAlloc, typename ArgAlloc, class Pair
, template<class ...> class Tuple, class... Args1, class... Args2>
typename container_detail::enable_if< container_detail::is_pair<Pair> >::type
- dispatch_uses_allocator( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t
+ dispatch_uses_allocator( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t
, Tuple<Args1...> t1, Tuple<Args2...> t2)
{
(dispatch_uses_allocator_index)( construct_alloc, arg_alloc, pair, t1, t2
@@ -347,7 +347,7 @@ BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BO
, template<class, class, class, class, class, class, class, class, class, class> class StdTuple\
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 > \
typename container_detail::enable_if< container_detail::is_pair<Pair> >::type\
- dispatch_uses_allocator(ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t\
+ dispatch_uses_allocator(ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
, StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::std::tr1::_Nil)> p\
, StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::std::tr1::_Nil)> q)\
{\
@@ -382,7 +382,7 @@ BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BO
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 > \
typename container_detail::enable_if< container_detail::is_pair<Pair> >::type\
dispatch_uses_allocator\
- ( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t\
+ ( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
, StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),N),::std::_Nil) > p\
, StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),M),::std::_Nil) > q)\
{\
@@ -406,6 +406,52 @@ BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BO
#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , class Pair, class KeyType, class ... Args>
+typename container_detail::enable_if< container_detail::is_pair<Pair>, void >::type
+ dispatch_uses_allocator
+ (ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args)
+{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first), ::boost::forward<KeyType>(k));
+ BOOST_TRY{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->second), ::boost::forward<Args>(args)...);
+ }
+ BOOST_CATCH(...) {
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(p->first));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+}
+
+#else
+
+#define BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE(N) \
+ template <typename ConstructAlloc, typename ArgAlloc, class Pair, class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
+ inline typename container_detail::enable_if\
+ < container_detail::is_pair<Pair>, void >::type\
+ dispatch_uses_allocator\
+ (ConstructAlloc &construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* p, try_emplace_t, \
+ BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first), ::boost::forward<KeyType>(k));\
+ BOOST_TRY{\
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->second) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ }\
+ BOOST_CATCH(...) {\
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(p->first));\
+ BOOST_RETHROW\
+ }\
+ BOOST_CATCH_END\
+ }\
+//
+BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE)
+#undef BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE
+
+#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
} //namespace container_detail
}} // namespace boost { namespace container {
diff --git a/boost/container/detail/hash_table.hpp b/boost/container/detail/hash_table.hpp
deleted file mode 100644
index 4bc5c901de..0000000000
--- a/boost/container/detail/hash_table.hpp
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
-template <class Value, unsigned int Options = 0, class Hash = hash<Value>, class Pred = equal_to<Value>,
- class Allocator = allocator<Value> >
-class hash_set
-{
-public:
- // types
- typedef Value key_type;
- typedef key_type value_type;
- typedef Hash hasher;
- typedef Pred key_equal;
- typedef Allocator allocator_type;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef typename allocator_traits<allocator_type>::pointer pointer;
- typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
- typedef typename allocator_traits<allocator_type>::size_type size_type;
- typedef typename allocator_traits<allocator_type>::difference_type difference_type;
-
- typedef /unspecified/ iterator;
- typedef /unspecified/ const_iterator;
- typedef /unspecified/ local_iterator;
- typedef /unspecified/ const_local_iterator;
-
- hash_set()
- noexcept(
- is_nothrow_default_constructible<hasher>::value &&
- is_nothrow_default_constructible<key_equal>::value &&
- is_nothrow_default_constructible<allocator_type>::value);
- explicit hash_set(size_type n, const hasher& hf = hasher(),
- const key_equal& eql = key_equal(),
- const allocator_type& a = allocator_type());
- template <class InputIterator>
- hash_set(InputIterator f, InputIterator l,
- size_type n = 0, const hasher& hf = hasher(),
- const key_equal& eql = key_equal(),
- const allocator_type& a = allocator_type());
- explicit hash_set(const allocator_type&);
- hash_set(const hash_set&);
- hash_set(const hash_set&, const Allocator&);
- hash_set(hash_set&&)
- noexcept(
- is_nothrow_move_constructible<hasher>::value &&
- is_nothrow_move_constructible<key_equal>::value &&
- is_nothrow_move_constructible<allocator_type>::value);
- hash_set(hash_set&&, const Allocator&);
- hash_set(initializer_list<value_type>, size_type n = 0,
- const hasher& hf = hasher(), const key_equal& eql = key_equal(),
- const allocator_type& a = allocator_type());
- ~hash_set();
- hash_set& operator=(const hash_set&);
- hash_set& operator=(hash_set&&)
- noexcept(
- allocator_type::propagate_on_container_move_assignment::value &&
- is_nothrow_move_assignable<allocator_type>::value &&
- is_nothrow_move_assignable<hasher>::value &&
- is_nothrow_move_assignable<key_equal>::value);
- hash_set& operator=(initializer_list<value_type>);
-
- allocator_type get_allocator() const noexcept;
-
- bool empty() const noexcept;
- size_type size() const noexcept;
- size_type max_size() const noexcept;
-
- iterator begin() noexcept;
- iterator end() noexcept;
- const_iterator begin() const noexcept;
- const_iterator end() const noexcept;
- const_iterator cbegin() const noexcept;
- const_iterator cend() const noexcept;
-
- template <class... Args>
- pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args);
- template <class... Args>
- iterator emplace_hint(const_iterator position, BOOST_FWD_REF(Args)... args);
- pair<iterator, bool> insert(const value_type& obj);
- pair<iterator, bool> insert(value_type&& obj);
- iterator insert(const_iterator hint, const value_type& obj);
- iterator insert(const_iterator hint, value_type&& obj);
- template <class InputIterator>
- void insert(InputIterator first, InputIterator last);
- void insert(initializer_list<value_type>);
-
- iterator erase(const_iterator position);
- size_type erase(const key_type& k);
- iterator erase(const_iterator first, const_iterator last);
- void clear() noexcept;
-
- void swap(hash_set&)
- noexcept(
- (!allocator_type::propagate_on_container_swap::value ||
- __is_nothrow_swappable<allocator_type>::value) &&
- __is_nothrow_swappable<hasher>::value &&
- __is_nothrow_swappable<key_equal>::value);
-
- hasher hash_function() const;
- key_equal key_eq() const;
-
- iterator find(const key_type& k);
- const_iterator find(const key_type& k) const;
- size_type count(const key_type& k) const;
- pair<iterator, iterator> equal_range(const key_type& k);
- pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
-
- size_type bucket_count() const noexcept;
- size_type max_bucket_count() const noexcept;
-
- size_type bucket_size(size_type n) const;
- size_type bucket(const key_type& k) const;
-
- local_iterator begin(size_type n);
- local_iterator end(size_type n);
- const_local_iterator begin(size_type n) const;
- const_local_iterator end(size_type n) const;
- const_local_iterator cbegin(size_type n) const;
- const_local_iterator cend(size_type n) const;
-
- float load_factor() const noexcept;
- float max_load_factor() const noexcept;
- void max_load_factor(float z);
- void rehash(size_type n);
- void reserve(size_type n);
-};
-
-template <class Key, class T, unsigned int Options = 0, class Hash = hash<Key>, class Pred = equal_to<Key>,
- class Allocator = allocator<pair<const Key, T> > >
-class hash_map
-{
-public:
- // types
- typedef Key key_type;
- typedef T mapped_type;
- typedef Hash hasher;
- typedef Pred key_equal;
- typedef Allocator allocator_type;
- typedef pair<const key_type, mapped_type> value_type;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef typename allocator_traits<allocator_type>::pointer pointer;
- typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
- typedef typename allocator_traits<allocator_type>::size_type size_type;
- typedef typename allocator_traits<allocator_type>::difference_type difference_type;
-
- typedef /unspecified/ iterator;
- typedef /unspecified/ const_iterator;
- typedef /unspecified/ local_iterator;
- typedef /unspecified/ const_local_iterator;
-
- hash_map()
- noexcept(
- is_nothrow_default_constructible<hasher>::value &&
- is_nothrow_default_constructible<key_equal>::value &&
- is_nothrow_default_constructible<allocator_type>::value);
- explicit hash_map(size_type n, const hasher& hf = hasher(),
- const key_equal& eql = key_equal(),
- const allocator_type& a = allocator_type());
- template <class InputIterator>
- hash_map(InputIterator f, InputIterator l,
- size_type n = 0, const hasher& hf = hasher(),
- const key_equal& eql = key_equal(),
- const allocator_type& a = allocator_type());
- explicit hash_map(const allocator_type&);
- hash_map(const hash_map&);
- hash_map(const hash_map&, const Allocator&);
- hash_map(hash_map&&)
- noexcept(
- is_nothrow_move_constructible<hasher>::value &&
- is_nothrow_move_constructible<key_equal>::value &&
- is_nothrow_move_constructible<allocator_type>::value);
- hash_map(hash_map&&, const Allocator&);
- hash_map(initializer_list<value_type>, size_type n = 0,
- const hasher& hf = hasher(), const key_equal& eql = key_equal(),
- const allocator_type& a = allocator_type());
- ~hash_map();
- hash_map& operator=(const hash_map&);
- hash_map& operator=(hash_map&&)
- noexcept(
- allocator_type::propagate_on_container_move_assignment::value &&
- is_nothrow_move_assignable<allocator_type>::value &&
- is_nothrow_move_assignable<hasher>::value &&
- is_nothrow_move_assignable<key_equal>::value);
- hash_map& operator=(initializer_list<value_type>);
-
- allocator_type get_allocator() const noexcept;
-
- bool empty() const noexcept;
- size_type size() const noexcept;
- size_type max_size() const noexcept;
-
- iterator begin() noexcept;
- iterator end() noexcept;
- const_iterator begin() const noexcept;
- const_iterator end() const noexcept;
- const_iterator cbegin() const noexcept;
- const_iterator cend() const noexcept;
-
- template <class... Args>
- pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args);
- template <class... Args>
- iterator emplace_hint(const_iterator position, BOOST_FWD_REF(Args)... args);
- pair<iterator, bool> insert(const value_type& obj);
- template <class P>
- pair<iterator, bool> insert(P&& obj);
- iterator insert(const_iterator hint, const value_type& obj);
- template <class P>
- iterator insert(const_iterator hint, P&& obj);
- template <class InputIterator>
- void insert(InputIterator first, InputIterator last);
- void insert(initializer_list<value_type>);
-
- iterator erase(const_iterator position);
- size_type erase(const key_type& k);
- iterator erase(const_iterator first, const_iterator last);
- void clear() noexcept;
-
- void swap(hash_map&)
- noexcept(
- (!allocator_type::propagate_on_container_swap::value ||
- __is_nothrow_swappable<allocator_type>::value) &&
- __is_nothrow_swappable<hasher>::value &&
- __is_nothrow_swappable<key_equal>::value);
-
- hasher hash_function() const;
- key_equal key_eq() const;
-
- iterator find(const key_type& k);
- const_iterator find(const key_type& k) const;
- size_type count(const key_type& k) const;
- pair<iterator, iterator> equal_range(const key_type& k);
- pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
-
- mapped_type& operator[](const key_type& k);
- mapped_type& operator[](key_type&& k);
-
- mapped_type& at(const key_type& k);
- const mapped_type& at(const key_type& k) const;
-
- size_type bucket_count() const noexcept;
- size_type max_bucket_count() const noexcept;
-
- size_type bucket_size(size_type n) const;
- size_type bucket(const key_type& k) const;
-
- local_iterator begin(size_type n);
- local_iterator end(size_type n);
- const_local_iterator begin(size_type n) const;
- const_local_iterator end(size_type n) const;
- const_local_iterator cbegin(size_type n) const;
- const_local_iterator cend(size_type n) const;
-
- float load_factor() const noexcept;
- float max_load_factor() const noexcept;
- void max_load_factor(float z);
- void rehash(size_type n);
- void reserve(size_type n);
-};
-
-*/
-
-template <class Key, class Value, class KeyOfValue, unsigned int Options = 0, class Hash = hash<Key>, class Pred = equal_to<Key>,
- class Allocator = allocator<Value> >
-class hash_table
-{
-public:
- // types
- typedef Value key_type;
- typedef key_type value_type;
- typedef Hash hasher;
- typedef Pred key_equal;
- typedef Allocator allocator_type;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef typename allocator_traits<allocator_type>::pointer pointer;
- typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
- typedef typename allocator_traits<allocator_type>::size_type size_type;
- typedef typename allocator_traits<allocator_type>::difference_type difference_type;
-
- typedef /unspecified/ iterator;
- typedef /unspecified/ const_iterator;
- typedef /unspecified/ local_iterator;
- typedef /unspecified/ const_local_iterator;
-
- hash_set()
- noexcept(
- is_nothrow_default_constructible<hasher>::value &&
- is_nothrow_default_constructible<key_equal>::value &&
- is_nothrow_default_constructible<allocator_type>::value);
- explicit hash_set(size_type n, const hasher& hf = hasher(),
- const key_equal& eql = key_equal(),
- const allocator_type& a = allocator_type());
- template <class InputIterator>
- hash_set(InputIterator f, InputIterator l,
- size_type n = 0, const hasher& hf = hasher(),
- const key_equal& eql = key_equal(),
- const allocator_type& a = allocator_type());
- explicit hash_set(const allocator_type&);
- hash_set(const hash_set&);
- hash_set(const hash_set&, const Allocator&);
- hash_set(hash_set&&)
- noexcept(
- is_nothrow_move_constructible<hasher>::value &&
- is_nothrow_move_constructible<key_equal>::value &&
- is_nothrow_move_constructible<allocator_type>::value);
- hash_set(hash_set&&, const Allocator&);
- hash_set(initializer_list<value_type>, size_type n = 0,
- const hasher& hf = hasher(), const key_equal& eql = key_equal(),
- const allocator_type& a = allocator_type());
- ~hash_set();
- hash_set& operator=(const hash_set&);
- hash_set& operator=(hash_set&&)
- noexcept(
- allocator_type::propagate_on_container_move_assignment::value &&
- is_nothrow_move_assignable<allocator_type>::value &&
- is_nothrow_move_assignable<hasher>::value &&
- is_nothrow_move_assignable<key_equal>::value);
- hash_set& operator=(initializer_list<value_type>);
-
- allocator_type get_allocator() const noexcept;
-
- bool empty() const noexcept;
- size_type size() const noexcept;
- size_type max_size() const noexcept;
-
- iterator begin() noexcept;
- iterator end() noexcept;
- const_iterator begin() const noexcept;
- const_iterator end() const noexcept;
- const_iterator cbegin() const noexcept;
- const_iterator cend() const noexcept;
-
- template <class... Args>
- pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args);
- template <class... Args>
- iterator emplace_hint(const_iterator position, BOOST_FWD_REF(Args)... args);
- pair<iterator, bool> insert(const value_type& obj);
- pair<iterator, bool> insert(value_type&& obj);
- iterator insert(const_iterator hint, const value_type& obj);
- iterator insert(const_iterator hint, value_type&& obj);
- template <class InputIterator>
- void insert(InputIterator first, InputIterator last);
- void insert(initializer_list<value_type>);
-
- iterator erase(const_iterator position);
- size_type erase(const key_type& k);
- iterator erase(const_iterator first, const_iterator last);
- void clear() noexcept;
-
- void swap(hash_set&)
- noexcept(
- (!allocator_type::propagate_on_container_swap::value ||
- __is_nothrow_swappable<allocator_type>::value) &&
- __is_nothrow_swappable<hasher>::value &&
- __is_nothrow_swappable<key_equal>::value);
-
- hasher hash_function() const;
- key_equal key_eq() const;
-
- iterator find(const key_type& k);
- const_iterator find(const key_type& k) const;
- size_type count(const key_type& k) const;
- pair<iterator, iterator> equal_range(const key_type& k);
- pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
-
- size_type bucket_count() const noexcept;
- size_type max_bucket_count() const noexcept;
-
- size_type bucket_size(size_type n) const;
- size_type bucket(const key_type& k) const;
-
- local_iterator begin(size_type n);
- local_iterator end(size_type n);
- const_local_iterator begin(size_type n) const;
- const_local_iterator end(size_type n) const;
- const_local_iterator cbegin(size_type n) const;
- const_local_iterator cend(size_type n) const;
-
- float load_factor() const noexcept;
- float max_load_factor() const noexcept;
- void max_load_factor(float z);
- void rehash(size_type n);
- void reserve(size_type n);
-};
diff --git a/boost/container/detail/mutex.hpp b/boost/container/detail/mutex.hpp
index 82e8810d0a..9743614c23 100644
--- a/boost/container/detail/mutex.hpp
+++ b/boost/container/detail/mutex.hpp
@@ -1,14 +1,9 @@
-// Copyright (C) 2000 Stephen Cleary
-//
-// Distributed under the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-// See http://www.boost.org for updates, documentation, and revision history.
-
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
+// (C) Copyright Stephen Cleary 2000
+// (C) Copyright Ion Gaztanaga 2015-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)
//
diff --git a/boost/container/detail/workaround.hpp b/boost/container/detail/workaround.hpp
index ed57718ba9..816d3cc84d 100644
--- a/boost/container/detail/workaround.hpp
+++ b/boost/container/detail/workaround.hpp
@@ -49,6 +49,10 @@
#define BOOST_CONTAINER_FALLTHOUGH BOOST_FALLTHOUGH;
#endif
+#if defined(BOOST_MSVC) && (_MSC_VER < 1400)
+ #define BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN
+#endif
+
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || (defined(BOOST_MSVC) && (BOOST_MSVC == 1700 || BOOST_MSVC == 1600))
#define BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
#endif
diff --git a/boost/container/new_allocator.hpp b/boost/container/new_allocator.hpp
index 9304a9cfa4..51065efa73 100644
--- a/boost/container/new_allocator.hpp
+++ b/boost/container/new_allocator.hpp
@@ -140,9 +140,9 @@ class new_allocator
//!Throws std::bad_alloc if there is no enough memory
pointer allocate(size_type count)
{
- if(BOOST_UNLIKELY(count > this->max_size()))
- throw_bad_alloc();
- return static_cast<T*>(::operator new(count*sizeof(T)));
+ if(BOOST_UNLIKELY(count > this->max_size()))
+ throw_bad_alloc();
+ return static_cast<T*>(::operator new(count*sizeof(T)));
}
//!Deallocates previously allocated memory.
diff --git a/boost/container/node_handle.hpp b/boost/container/node_handle.hpp
index 300b4713ad..c46313cc4f 100644
--- a/boost/container/node_handle.hpp
+++ b/boost/container/node_handle.hpp
@@ -131,6 +131,9 @@ class node_handle
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);
@@ -323,7 +326,7 @@ class node_handle
if(was_nh_non_null){
if(was_this_non_null){
- if(ator_traits::propagate_on_container_swap){
+ if(ator_traits::propagate_on_container_swap::value){
::boost::adl_move_swap(this->node_alloc(), nh.node_alloc());
}
}
diff --git a/boost/container/small_vector.hpp b/boost/container/small_vector.hpp
index e23b54f8ac..14446247ac 100644
--- a/boost/container/small_vector.hpp
+++ b/boost/container/small_vector.hpp
@@ -507,7 +507,7 @@ class small_vector : public small_vector_base<T, Allocator>
public:
BOOST_CONTAINER_FORCEINLINE small_vector()
- BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value)
+ BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value)
: base_type(initial_capacity_t(), internal_capacity())
{}
diff --git a/boost/container/string.hpp b/boost/container/string.hpp
index 1e47abaaf0..7b780fd588 100644
--- a/boost/container/string.hpp
+++ b/boost/container/string.hpp
@@ -37,16 +37,19 @@
#include <boost/container/detail/next_capacity.hpp>
#include <boost/container/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/intrusive/pointer_traits.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/traits.hpp>
+
#include <boost/static_assert.hpp>
-#include <boost/intrusive/pointer_traits.hpp>
#include <boost/core/no_exceptions_support.hpp>
-#include <boost/container/detail/minimal_char_traits_header.hpp>
#include <boost/functional/hash.hpp>
-
#include <algorithm>
#include <functional> //bind2nd, etc.
#include <iosfwd>
@@ -56,8 +59,12 @@
#include <locale>
#include <cstddef>
#include <climits>
-#include <boost/container/detail/type_traits.hpp>
-#include <boost/move/traits.hpp>
+
+//std
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list> //for std::initializer_list
+#endif
+
namespace boost {
namespace container {
@@ -615,6 +622,17 @@ class basic_string
this->assign(s.begin(), s.end());
}
+ //! <b>Effects</b>: Same as basic_string(sv.data(), sv.size(), a).
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor or allocation throws.
+ template<template <class, class> class BasicStringView>
+ explicit basic_string(BasicStringView<CharT, Traits> sv, const Allocator& a = Allocator())
+ : base_t(allocator_traits_type::select_on_container_copy_construction(a))
+ {
+ this->priv_terminate_string();
+ this->assign(sv);
+ }
+
//! <b>Effects</b>: Move constructor. Moves s's resources to *this.
//!
//! <b>Throws</b>: Nothing.
@@ -780,6 +798,17 @@ class basic_string
this->assign(f, l);
}
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Same as basic_string(il.begin(), il.end(), a).
+ //!
+ basic_string(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
+ : base_t(a)
+ {
+ this->priv_terminate_string();
+ this->assign(il.begin(), il.end());
+ }
+ #endif
+
//! <b>Effects</b>: Destroys the basic_string. All used memory is deallocated.
//!
//! <b>Throws</b>: Nothing.
@@ -852,13 +881,30 @@ class basic_string
}
//! <b>Effects</b>: Assignment from a null-terminated c-string.
+ //!
basic_string& operator=(const CharT* s)
{ return this->assign(s, s + Traits::length(s)); }
- //! <b>Effects</b>: Assignment from character.
+ //! <b>Effects</b>: Returns *this = basic_string(1, c).
+ //!
basic_string& operator=(CharT c)
{ return this->assign(static_cast<size_type>(1), c); }
+ //! <b>Effects</b>: Equivalent to return assign(sv).
+ //!
+ template<template <class, class> class BasicStringView>
+ basic_string& operator=(BasicStringView<CharT, Traits> sv)
+ { return this->assign(sv.data(), sv.size()); }
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Returns *this = basic_string(il);
+ //!
+ basic_string& operator=(std::initializer_list<CharT> il)
+ {
+ return this->assign(il.begin(), il.end());
+ }
+ #endif
+
//! <b>Effects</b>: Returns a copy of the internal allocator.
//!
//! <b>Throws</b>: If allocator's copy constructor throws.
@@ -1256,6 +1302,14 @@ class basic_string
basic_string& operator+=(const basic_string& s)
{ return this->append(s); }
+ //! <b>Effects</b>: Same as `return append(sv)`.
+ //!
+ template<template<class, class> class BasicStringView>
+ basic_string& operator+=(BasicStringView<CharT, Traits> sv)
+ {
+ return this->append(sv);
+ }
+
//! <b>Effects</b>: Calls append(s).
//!
//! <b>Returns</b>: *this
@@ -1268,12 +1322,27 @@ class basic_string
basic_string& operator+=(CharT c)
{ this->push_back(c); return *this; }
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Returns append(il)
+ //!
+ basic_string& operator+=(std::initializer_list<CharT> il)
+ {
+ return this->append(il);
+ }
+ #endif
+
//! <b>Effects</b>: Calls append(str.data(), str.size()).
//!
//! <b>Returns</b>: *this
basic_string& append(const basic_string& s)
{ return this->append(s.begin(), s.end()); }
+ //! <b>Effects</b>: Same as return append(sv.data(), sv.size()).
+ //!
+ template<template<class, class> class BasicStringView>
+ basic_string& append(BasicStringView<CharT, Traits> sv)
+ { return this->append(sv.data(), sv.size()); }
+
//! <b>Requires</b>: pos <= str.size()
//!
//! <b>Effects</b>: Determines the effective length rlen of the string to append
@@ -1282,7 +1351,7 @@ class basic_string
//! <b>Throws</b>: If memory allocation throws and out_of_range if pos > str.size()
//!
//! <b>Returns</b>: *this
- basic_string& append(const basic_string& s, size_type pos, size_type n)
+ basic_string& append(const basic_string& s, size_type pos, size_type n = npos)
{
if (pos > s.size())
throw_out_of_range("basic_string::append out of range position");
@@ -1326,7 +1395,17 @@ class basic_string
basic_string& append(InputIter first, InputIter last)
{ this->insert(this->end(), first, last); return *this; }
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Returns append(il.begin(), il.size()).
+ //!
+ basic_string& append(std::initializer_list<CharT> il)
+ {
+ return this->append(il.begin(), il.size());
+ }
+ #endif
+
//! <b>Effects</b>: Equivalent to append(static_cast<size_type>(1), c).
+ //!
void push_back(CharT c)
{
const size_type old_size = this->priv_size();
@@ -1348,6 +1427,13 @@ class basic_string
basic_string& assign(const basic_string& s)
{ return this->operator=(s); }
+ //! <b>Effects</b>: Equivalent to return assign(sv.data(), sv.size()).
+ //!
+ //! <b>Returns</b>: *this
+ template<template <class, class> class BasicStringView>
+ basic_string& assign(BasicStringView<CharT, Traits> sv)
+ { return this->operator=(sv); }
+
//! <b>Effects</b>: The function replaces the string controlled by *this
//! with a string of length str.size() whose elements are a copy of the string
//! controlled by str. Leaves str in a valid but unspecified state.
@@ -1440,6 +1526,15 @@ class basic_string
return *this;
}
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Returns assign(il.begin(), il.size()).
+ //!
+ basic_string& assign(std::initializer_list<CharT> il)
+ {
+ return this->assign(il.begin(), il.size());
+ }
+ #endif
+
//! <b>Requires</b>: pos <= size().
//!
//! <b>Effects</b>: Calls insert(pos, str.data(), str.size()).
@@ -1466,7 +1561,7 @@ class basic_string
//! <b>Throws</b>: If memory allocation throws or out_of_range if pos1 > size() or pos2 > str.size().
//!
//! <b>Returns</b>: *this
- basic_string& insert(size_type pos1, const basic_string& s, size_type pos2, size_type n)
+ basic_string& insert(size_type pos1, const basic_string& s, size_type pos2, size_type n = npos)
{
const size_type sz = this->size();
const size_type str_size = s.size();
@@ -1537,6 +1632,12 @@ class basic_string
return *this;
}
+ //! <b>Effects</b>: Same as `return insert(pos, sv.data(), sv.size())`.
+ //!
+ template<template<class, class> class BasicStringView>
+ basic_string& insert(size_type pos, BasicStringView<CharT, Traits> sv)
+ { return this->insert(pos, sv.data(), sv.size()); }
+
//! <b>Requires</b>: p is a valid iterator on *this.
//!
//! <b>Effects</b>: inserts a copy of c before the character referred to by p.
@@ -1549,7 +1650,6 @@ class basic_string
return this->priv_addr() + new_offset;
}
-
//! <b>Requires</b>: p is a valid iterator on *this.
//!
//! <b>Effects</b>: Inserts n copies of c before the character referred to by p.
@@ -1695,6 +1795,17 @@ class basic_string
}
#endif
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: As if by insert(p, il.begin(), il.end()).
+ //!
+ //! <b>Returns</b>: An iterator which refers to the copy of the first inserted
+ //! character, or p if i1 is empty.
+ iterator insert(const_iterator p, std::initializer_list<CharT> il)
+ {
+ return this->insert(p, il.begin(), il.end());
+ }
+ #endif
+
//! <b>Effects</b>: Removes the last element from the container.
//!
//! <b>Throws</b>: Nothing.
@@ -1801,6 +1912,14 @@ class basic_string
, str.begin(), str.end());
}
+ //! <b>Effects</b>: Calls `return replace(pos1, n1, sv.data(), sv.size());`.
+ //!
+ template<template<class, class> class BasicStringView>
+ basic_string& replace(size_type pos1, size_type n1, BasicStringView<CharT, Traits> sv)
+ {
+ return this->replace(pos1, n1, sv.data(), sv.size());
+ }
+
//! <b>Requires</b>: pos1 <= size() and pos2 <= str.size().
//!
//! <b>Effects</b>: Determines the effective length rlen of the string to be
@@ -1811,18 +1930,26 @@ class basic_string
//!
//! <b>Returns</b>: *this
basic_string& replace(size_type pos1, size_type n1,
- const basic_string& str, size_type pos2, size_type n2)
+ const basic_string& str, size_type pos2, size_type n2 = npos)
{
- if (pos1 > this->size() || pos2 > str.size())
+ if (pos2 > str.size())
throw_out_of_range("basic_string::replace out of range position");
- const size_type len1 = container_detail::min_value(n1, this->size() - pos1);
- const size_type len2 = container_detail::min_value(n2, str.size() - pos2);
- if (this->size() - len1 >= this->max_size() - len2)
- throw_length_error("basic_string::replace max_size() exceeded");
- const pointer addr = this->priv_addr();
- const pointer straddr = str.priv_addr();
- return this->replace(addr + pos1, addr + pos1 + len1,
- straddr + pos2, straddr + pos2 + len2);
+ return this->replace(pos1, n1, str.data()+pos2, container_detail::min_value(n2, str.size() - pos2));
+ }
+
+ //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > sv.size().
+ //!
+ //! <b>Effects</b>: Determines the effective length rlen of the string to be inserted as the
+ //! smaller of n2 and sv.size() - pos2 and calls `replace(pos1, n1, sv.data() + pos2, rlen)`.
+ //!
+ //! <b>Returns</b>: *this.
+ template<template<class, class> class BasicStringView>
+ basic_string& replace(size_type pos1, size_type n1, BasicStringView<CharT, Traits> sv,
+ size_type pos2, size_type n2 = npos)
+ {
+ if (pos2 > sv.size())
+ throw_out_of_range("basic_string::replace out of range position");
+ return this->replace(pos1, n1, sv.data()+pos2, container_detail::min_value(n2, sv.size() - pos2));
}
//! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
@@ -1836,7 +1963,7 @@ class basic_string
//! the original string controlled by *this beginning at position pos + xlen.
//!
//! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
- //! if the length of the resulting string would exceed max_size()
+ //! if the length of the resulting string would exceed max_size()
//!
//! <b>Returns</b>: *this
basic_string& replace(size_type pos1, size_type n1, const CharT* s, size_type n2)
@@ -1844,10 +1971,11 @@ class basic_string
if (pos1 > this->size())
throw_out_of_range("basic_string::replace out of range position");
const size_type len = container_detail::min_value(n1, this->size() - pos1);
- if (n2 > this->max_size() || size() - len >= this->max_size() - n2)
+ const size_type max_size = this->max_size();
+ if (n2 > max_size || (this->size() - len) >= (max_size - n2))
throw_length_error("basic_string::replace max_size() exceeded");
- const pointer addr = this->priv_addr();
- return this->replace(addr + pos1, addr + pos1 + len, s, s + n2);
+ const pointer addr = this->priv_addr() + pos1;
+ return this->replace(addr, addr + len, s, s + n2);
}
//! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
@@ -1866,15 +1994,7 @@ class basic_string
//! <b>Returns</b>: *this
basic_string& replace(size_type pos, size_type n1, const CharT* s)
{
- if (pos > this->size())
- throw_out_of_range("basic_string::replace out of range position");
- const size_type len = container_detail::min_value(n1, this->size() - pos);
- const size_type n2 = Traits::length(s);
- if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2)
- throw_length_error("basic_string::replace max_size() exceeded");
- const pointer addr = this->priv_addr();
- return this->replace(addr + pos, addr + pos + len,
- s, s + Traits::length(s));
+ return this->replace(pos, n1, s, Traits::length(s));
}
//! <b>Requires</b>: pos1 <= size().
@@ -1904,7 +2024,7 @@ class basic_string
//!
//! <b>Returns</b>: *this
basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str)
- { return this->replace(i1, i2, str.begin(), str.end()); }
+ { return this->replace(i1, i2, str.data(), str.data()+str.size()); }
//! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges and
//! s points to an array of at least n elements
@@ -2004,6 +2124,32 @@ class basic_string
}
#endif
+ //! <b>Requires</b>: [begin(), i1) and [i1, i2) are valid ranges.
+ //!
+ //! <b>Effects</b>: Calls `replace(i1 - begin(), i2 - i1, sv).`.
+ //!
+ //! <bReturns</b>: *this.
+ template<template <class, class> class BasicStringView>
+ basic_string& replace(const_iterator i1, const_iterator i2, BasicStringView<CharT, Traits> sv)
+ {
+ return this->replace( static_cast<size_type>(i1 - this->cbegin())
+ , static_cast<size_type>(i2 - i1), sv);
+ }
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Requires</b>: [begin(), i1) and [i1, i2) are valid ranges.
+ //!
+ //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, il.begin(), il.size()).
+ //!
+ //! <bReturns</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())
+ , static_cast<size_type>(i2 - i1)
+ , il.begin(), il.size());
+ }
+ #endif
+
//! <b>Requires</b>: pos <= size()
//!
//! <b>Effects</b>: Determines the effective length rlen of the string to copy as the
@@ -2059,6 +2205,31 @@ class basic_string
const CharT* data() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::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()); }
+
+ #ifndef BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN
+ //! <b>Returns</b>: a string_view to the characters in the string.
+ //!
+ //! <b>Complexity</b>: constant time.
+ template<template <class, class> class BasicStringView>
+ operator BasicStringView<CharT, Traits>() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->to_view< BasicStringView<CharT, Traits> >(); }
+ #endif
+
+ //! <b>Returns</b>: a string_view to the characters in the string.
+ //!
+ //! <b>Complexity</b>: constant time.
+ //!
+ //! <b>Note</b>: This function is available to write portable code for compilers
+ //! that don't support templated conversion operators.
+ template<class BasicStringView>
+ BasicStringView to_view() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return BasicStringView(this->data(), this->size()); }
+
//////////////////////////////////////////////
//
// string operations
@@ -2066,7 +2237,8 @@ class basic_string
//////////////////////////////////////////////
//! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both
- //! of the following conditions obtain: 19 pos <= xpos and xpos + str.size() <= size();
+ //! of the following conditions hold:
+ //! 1) pos <= xpos and xpos + str.size() <= size();
//! 2) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
//!
//! <b>Throws</b>: Nothing
@@ -2075,6 +2247,18 @@ class basic_string
size_type find(const basic_string& s, size_type pos = 0) const
{ return find(s.c_str(), pos, s.size()); }
+ //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both
+ //! of the following conditions hold:
+ //! 1) pos <= xpos and xpos + sv.size() <= size();
+ //! 2) traits::eq(at(xpos+I), sv.at(I)) for all elements I of the string controlled by sv.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <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(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
+ { return find(sv.data(), pos, sv.size()); }
+
//! <b>Requires</b>: s points to an array of at least n elements of CharT.
//!
//! <b>Throws</b>: Nothing
@@ -2132,6 +2316,18 @@ class basic_string
size_type rfind(const basic_string& str, size_type pos = npos) const
{ return rfind(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 + sv.size() <= size();
+ //! b) traits::eq(at(xpos+I), sv.at(I)) for all elements I of the string controlled by sv.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <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 rfind(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
+ { return rfind(sv.data(), pos, sv.size()); }
+
//! <b>Requires</b>: s points to an array of at least n elements of CharT.
//!
//! <b>Throws</b>: Nothing
@@ -2188,8 +2384,19 @@ class basic_string
//! <b>Throws</b>: Nothing
//!
//! <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& s, size_type pos = 0) const
- { return find_first_of(s.c_str(), pos, s.size()); }
+ size_type find_first_of(const basic_string& str, size_type pos = 0) const
+ { return 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();
+ //! b) traits::eq(at(xpos), sv.at(I)) for some element I of the string controlled by sv.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <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()); }
//! <b>Requires</b>: s points to an array of at least n elements of CharT.
//!
@@ -2236,6 +2443,17 @@ class basic_string
size_type find_last_of(const basic_string& str, size_type pos = npos) const
{ return 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)
+ //! traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <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()); }
+
//! <b>Requires</b>: s points to an array of at least n elements of CharT.
//!
//! <b>Throws</b>: Nothing
@@ -2282,6 +2500,18 @@ class basic_string
size_type find_first_not_of(const basic_string& str, size_type pos = 0) const
{ return find_first_not_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(); b) traits::eq(at(xpos), sv.at(I)) for no
+ //! element I of the string controlled by sv.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <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_not_of(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
+ { return find_first_not_of(sv.data(), pos, sv.size()); }
+
//! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
//!
//! <b>Throws</b>: Nothing
@@ -2335,6 +2565,17 @@ class basic_string
size_type find_last_not_of(const basic_string& str, size_type pos = npos) const
{ return find_last_not_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) traits::eq(at(xpos), sv.at(I)) for no element I of the string controlled by sv.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <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_not_of(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
+ { return find_last_not_of(sv.data(), pos, sv.size()); }
+
//! <b>Requires</b>: s points to an array of at least n elements of CharT.
//!
//! <b>Throws</b>: Nothing
@@ -2398,7 +2639,7 @@ class basic_string
addr + pos + container_detail::min_value(n, size() - pos), this->alloc());
}
- //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
+ //! <b>Effects</b>: Determines the effective length rlen of the string to compare as
//! the smaller of size() and str.size(). The function then compares the two strings by
//! calling traits::compare(data(), str.data(), rlen).
//!
@@ -2414,10 +2655,21 @@ class basic_string
return s_compare(addr, addr + this->priv_size(), str_addr, str_addr + str.priv_size());
}
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: compare(basic_string(sv)).
+ template<template <class, class> class BasicStringView>
+ int compare(BasicStringView<CharT,Traits> sv) const
+ {
+ const pointer addr = this->priv_addr();
+ return s_compare(addr, addr + this->priv_size(), sv.data(), sv.data() + sv.size());
+ }
+
//! <b>Requires</b>: pos1 <= size()
//!
- //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
- //! the smaller of
+ //! <b>Effects</b>: Determines the effective length rlen of the string to compare as
+ //! the smaller of (this->size() - pos1), n1 and str.size(). The function then compares the two strings by
+ //! calling traits::compare(data()+pos1, str.data(), rlen).
//!
//! <b>Throws</b>: out_of_range if pos1 > size()
//!
@@ -2433,6 +2685,22 @@ class basic_string
str_addr, str_addr + str.priv_size());
}
+ //! <b>Requires</b>: pos1 <= size()
+ //!
+ //! <b>Throws</b>: out_of_range if pos1 > size()
+ //!
+ //! <b>Returns</b>:basic_string(*this,pos1,n1).compare(sv).
+ template<template <class, class> class BasicStringView>
+ int compare(size_type pos1, size_type n1, BasicStringView<CharT,Traits> sv) const
+ {
+ if (pos1 > this->size())
+ throw_out_of_range("basic_string::compare out of range position");
+ const pointer addr = this->priv_addr() + pos1;
+ const CharT* str_addr = sv.data();
+ return s_compare(addr, addr + container_detail::min_value(n1, this->size() - pos1),
+ str_addr, str_addr + sv.size());
+ }
+
//! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
//!
//! <b>Effects</b>: Determines the effective length rlen of the string to copy as
@@ -2441,16 +2709,33 @@ class basic_string
//! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > str.size()
//!
//! <b>Returns</b>: basic_string(*this, pos1, n1).compare(basic_string(str, pos2, n2)).
- int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2) const
+ int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2 = npos) const
{
if (pos1 > this->size() || pos2 > str.size())
throw_out_of_range("basic_string::compare out of range position");
- const pointer addr = this->priv_addr();
- const pointer str_addr = str.priv_addr();
- return s_compare(addr + pos1,
- addr + pos1 + container_detail::min_value(n1, this->size() - pos1),
- str_addr + pos2,
- str_addr + pos2 + container_detail::min_value(n2, str.size() - pos2));
+ const pointer addr = this->priv_addr() + pos1;
+ const pointer str_addr = str.priv_addr() + pos2;
+ return s_compare(addr, addr + container_detail::min_value(n1, this->size() - pos1),
+ str_addr, str_addr + container_detail::min_value(n2, str.size() - pos2));
+ }
+
+ //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
+ //!
+ //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
+ //! the smaller of
+ //!
+ //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > sv.size()
+ //!
+ //! <b>Returns</b>: basic_string(*this, pos1, n1).compare(BasicStringView<CharT, Traits>(sv, pos2, n2)).
+ template<template <class, class> class BasicStringView>
+ int compare(size_type pos1, size_type n1, BasicStringView<CharT,Traits> sv, size_type pos2, size_type n2) const
+ {
+ if (pos1 > this->size() || pos2 > sv.size())
+ throw_out_of_range("basic_string::compare out of range position");
+ const pointer addr = this->priv_addr() + pos1;
+ const CharT * str_addr = sv.data() + pos2;
+ return s_compare(addr, addr + container_detail::min_value(n1, this->size() - pos1),
+ str_addr, str_addr + container_detail::min_value(n2, sv.size() - pos2));
}
//! <b>Throws</b>: Nothing
@@ -2462,7 +2747,6 @@ class basic_string
return s_compare(addr, addr + this->priv_size(), s, s + Traits::length(s));
}
-
//! <b>Requires</b>: pos1 > size() and s points to an array of at least n2 elements of CharT.
//!
//! <b>Throws</b>: out_of_range if pos1 > size()
@@ -2515,8 +2799,8 @@ class basic_string
}
}
- static int s_compare(const_pointer f1, const_pointer l1,
- const_pointer f2, const_pointer l2)
+ template<class It1, class It2>
+ static int s_compare(It1 f1, It1 l1, It2 f2, It2 l2)
{
const difference_type n1 = l1 - f1;
const difference_type n2 = l2 - f2;
@@ -2753,8 +3037,7 @@ template <class CharT, class Traits, class Allocator> inline
template <class CharT, class Traits, class Allocator>
inline bool
-operator==(const basic_string<CharT,Traits,Allocator>& x,
- const basic_string<CharT,Traits,Allocator>& y)
+operator==(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
{
return x.size() == y.size() &&
Traits::compare(x.data(), y.data(), x.size()) == 0;
@@ -2776,10 +3059,25 @@ operator==(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
return x.size() == n && Traits::compare(x.data(), s, n) == 0;
}
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline bool
+operator==( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
+{
+ return x.size() == y.size() &&
+ Traits::compare(x.data(), y.data(), x.size()) == 0;
+}
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline bool
+operator==( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
+{
+ return x.size() == y.size() &&
+ Traits::compare(x.data(), y.data(), x.size()) == 0;
+}
+
template <class CharT, class Traits, class Allocator>
inline bool
-operator!=(const basic_string<CharT,Traits,Allocator>& x,
- const basic_string<CharT,Traits,Allocator>& y)
+operator!=(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
{ return !(x == y); }
template <class CharT, class Traits, class Allocator>
@@ -2793,15 +3091,22 @@ operator!=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
{ return !(x == s); }
-// Operator< (and also >, <=, and >=).
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline bool
+operator!=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
+ { return !(x == y); }
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline bool
+operator!=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
+ { return !(x == y); }
+// Operator< (and also >, <=, and >=).
template <class CharT, class Traits, class Allocator>
inline bool
operator<(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
{
return x.compare(y) < 0;
-// return basic_string<CharT,Traits,Allocator>
-// ::s_compare(x.begin(), x.end(), y.begin(), y.end()) < 0;
}
template <class CharT, class Traits, class Allocator>
@@ -2809,26 +3114,28 @@ inline bool
operator<(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
{
return y.compare(s) > 0;
-// basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
-// return basic_string<CharT,Traits,Allocator>
-// ::s_compare(s, s + n, y.begin(), y.end()) < 0;
}
template <class CharT, class Traits, class Allocator>
inline bool
-operator<(const basic_string<CharT,Traits,Allocator>& x,
- const CharT* s)
+operator<(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
{
return x.compare(s) < 0;
-// basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
-// return basic_string<CharT,Traits,Allocator>
-// ::s_compare(x.begin(), x.end(), s, s + n) < 0;
}
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline bool
+operator<( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
+ { return y.compare(x) > 0; }
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline bool
+operator<( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
+ { return x.compare(y) < 0; }
+
template <class CharT, class Traits, class Allocator>
inline bool
-operator>(const basic_string<CharT,Traits,Allocator>& x,
- const basic_string<CharT,Traits,Allocator>& y) {
+operator>(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y) {
return y < x;
}
@@ -2845,10 +3152,19 @@ operator>(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
return s < x;
}
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline bool
+operator>( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
+ { return y < x; }
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline bool
+operator>( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
+ { return y < x; }
+
template <class CharT, class Traits, class Allocator>
inline bool
-operator<=(const basic_string<CharT,Traits,Allocator>& x,
- const basic_string<CharT,Traits,Allocator>& y)
+operator<=(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
{
return !(y < x);
}
@@ -2863,6 +3179,17 @@ inline bool
operator<=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
{ return !(s < x); }
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline bool
+operator<=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
+ { return !(y < x); }
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline bool
+operator<=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
+ { return !(y < x); }
+
template <class CharT, class Traits, class Allocator>
inline bool
operator>=(const basic_string<CharT,Traits,Allocator>& x,
@@ -2879,6 +3206,16 @@ inline bool
operator>=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
{ return !(x < s); }
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline bool
+operator>=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
+ { return !(x < y); }
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline bool
+operator>=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
+ { return !(x < y); }
+
// Swap.
template <class CharT, class Traits, class Allocator>
inline void swap(basic_string<CharT,Traits,Allocator>& x, basic_string<CharT,Traits,Allocator>& y)
diff --git a/boost/container/vector.hpp b/boost/container/vector.hpp
index 5d7d765e3d..336d616007 100644
--- a/boost/container/vector.hpp
+++ b/boost/container/vector.hpp
@@ -1735,9 +1735,10 @@ class vector
{
if (BOOST_LIKELY(this->room_enough())){
//There is more memory, just construct a new object at the end
- allocator_traits_type::construct(this->m_holder.alloc(), this->priv_raw_end(), ::boost::forward<Args>(args)...);
+ T* const p = this->priv_raw_end();
+ allocator_traits_type::construct(this->m_holder.alloc(), p, ::boost::forward<Args>(args)...);
++this->m_holder.m_size;
- return *this->priv_raw_end();
+ return *p;
}
else{
typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
@@ -1793,10 +1794,11 @@ class vector
BOOST_CONTAINER_FORCEINLINE reference emplace_back(BOOST_MOVE_UREF##N)\
{\
if (BOOST_LIKELY(this->room_enough())){\
+ T* const p = this->priv_raw_end();\
allocator_traits_type::construct (this->m_holder.alloc()\
, this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
++this->m_holder.m_size;\
- return *this->priv_raw_end();\
+ return *p;\
}\
else{\
typedef container_detail::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
@@ -2255,7 +2257,7 @@ class vector
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 - addr)/sizeof(size_type);
+ 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){
diff --git a/boost/context/all.hpp b/boost/context/all.hpp
index 44b734cdb8..193eefb937 100644
--- a/boost/context/all.hpp
+++ b/boost/context/all.hpp
@@ -1,10 +1,10 @@
-// Copyright Oliver Kowalke 2014.
+// Copyright Oliver Kowalke 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/context/execution_context.hpp>
+#include <boost/context/continuation.hpp>
#include <boost/context/fixedsize_stack.hpp>
#include <boost/context/pooled_fixedsize_stack.hpp>
#include <boost/context/protected_fixedsize_stack.hpp>
diff --git a/boost/context/continuation.hpp b/boost/context/continuation.hpp
new file mode 100644
index 0000000000..6a50713158
--- /dev/null
+++ b/boost/context/continuation.hpp
@@ -0,0 +1,554 @@
+
+// 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_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 };
+#else
+ return { std::exchange( cc.t_.fctx, nullptr), nullptr };
+#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/execution_context_v1.hpp b/boost/context/execution_context_v1.hpp
index f3bef45fb6..d23013215a 100644
--- a/boost/context/execution_context_v1.hpp
+++ b/boost/context/execution_context_v1.hpp
@@ -60,7 +60,7 @@ struct data_t {
void * data;
};
-struct activation_record {
+struct BOOST_CONTEXT_DECL activation_record {
typedef boost::intrusive_ptr< activation_record > ptr_t;
thread_local static ptr_t current_rec;
@@ -72,7 +72,7 @@ struct activation_record {
// used for toplevel-context
// (e.g. main context, thread-entry context)
- constexpr activation_record() = default;
+ activation_record() = default;
activation_record( fcontext_t fctx_, stack_context sctx_) noexcept :
fctx{ fctx_ },
@@ -146,7 +146,7 @@ struct activation_record {
}
};
-struct activation_record_initializer {
+struct BOOST_CONTEXT_DECL activation_record_initializer {
activation_record_initializer() noexcept;
~activation_record_initializer();
};
diff --git a/boost/context/execution_context_v2.hpp b/boost/context/execution_context_v2.hpp
index a037687258..bbd4eb1024 100644
--- a/boost/context/execution_context_v2.hpp
+++ b/boost/context/execution_context_v2.hpp
@@ -103,7 +103,7 @@ public:
transfer_t run( transfer_t t) {
Ctx from{ t.fctx };
- typename Ctx::args_tpl_t args = std::move( * static_cast< typename Ctx::args_tpl_t * >( t.data) );
+ typename Ctx::args_tpl_t args = std::move( std::get<1>( * static_cast< std::tuple< std::exception_ptr, typename Ctx::args_tpl_t > * >( t.data) ) );
auto tpl = std::tuple_cat(
params_,
std::forward_as_tuple( std::move( from) ),
@@ -141,7 +141,7 @@ private:
}
public:
- constexpr execution_context() noexcept = default;
+ execution_context() noexcept = default;
#if defined(BOOST_USE_SEGMENTED_STACKS)
// segmented-stack requires to preserve the segments of the `current` context
diff --git a/boost/context/execution_context_v2_void.ipp b/boost/context/execution_context_v2_void.ipp
index fdf15cd564..6e8f85a8dc 100644
--- a/boost/context/execution_context_v2_void.ipp
+++ b/boost/context/execution_context_v2_void.ipp
@@ -80,7 +80,7 @@ private:
}
public:
- constexpr execution_context() noexcept = default;
+ execution_context() noexcept = default;
#if defined(BOOST_USE_SEGMENTED_STACKS)
// segmented-stack requires to preserve the segments of the `current` context
diff --git a/boost/context/fixedsize_stack.hpp b/boost/context/fixedsize_stack.hpp
index c04dd1b7f6..46e7866891 100644
--- a/boost/context/fixedsize_stack.hpp
+++ b/boost/context/fixedsize_stack.hpp
@@ -4,81 +4,10 @@
// (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
+#if defined(BOOST_WINDOWS)
+# include <boost/context/windows/fixedsize_stack.hpp>
+#else
+# include <boost/context/posix/fixedsize_stack.hpp>
#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) {
- BOOST_ASSERT( traits_type::minimum_size() <= size_);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_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);
- BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
-
-#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/fixedsize_stack.hpp b/boost/context/posix/fixedsize_stack.hpp
new file mode 100644
index 0000000000..756b260bda
--- /dev/null
+++ b/boost/context/posix/fixedsize_stack.hpp
@@ -0,0 +1,80 @@
+
+// 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 7d1b789d01..f36d451b40 100644
--- a/boost/context/posix/protected_fixedsize_stack.hpp
+++ b/boost/context/posix/protected_fixedsize_stack.hpp
@@ -46,8 +46,6 @@ public:
basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
size_( size) {
- BOOST_ASSERT( traits_type::minimum_size() <= size_);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
}
stack_context allocate() {
@@ -88,8 +86,6 @@ public:
void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
BOOST_ASSERT( sctx.sp);
- BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
#if defined(BOOST_USE_VALGRIND)
VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
diff --git a/boost/context/posix/segmented_stack.hpp b/boost/context/posix/segmented_stack.hpp
index 25842b6d32..e3d2efcb5b 100644
--- a/boost/context/posix/segmented_stack.hpp
+++ b/boost/context/posix/segmented_stack.hpp
@@ -47,8 +47,6 @@ public:
basic_segmented_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
size_( size) {
- BOOST_ASSERT( traits_type::minimum_size() <= size_);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
}
stack_context allocate() {
diff --git a/boost/context/windows/fixedsize_stack.hpp b/boost/context/windows/fixedsize_stack.hpp
new file mode 100644
index 0000000000..a67c315c47
--- /dev/null
+++ b/boost/context/windows/fixedsize_stack.hpp
@@ -0,0 +1,80 @@
+
+// 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 cd59764c93..437f091088 100644
--- a/boost/context/windows/protected_fixedsize_stack.hpp
+++ b/boost/context/windows/protected_fixedsize_stack.hpp
@@ -38,8 +38,6 @@ public:
basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
size_( size) {
- BOOST_ASSERT( traits_type::minimum_size() <= size_);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
}
stack_context allocate() {
@@ -74,8 +72,6 @@ public:
void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
BOOST_ASSERT( sctx.sp);
- BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
- BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
void * vp = static_cast< char * >( sctx.sp) - sctx.size;
::VirtualFree( vp, 0, MEM_RELEASE);
diff --git a/boost/convert/base.hpp b/boost/convert/base.hpp
index 41c0e4b29b..27931194cc 100644
--- a/boost/convert/base.hpp
+++ b/boost/convert/base.hpp
@@ -33,18 +33,18 @@ namespace boost { namespace cnv
template<typename derived_type>
struct boost::cnv::cnvbase
{
- typedef cnvbase this_type;
- typedef int int_type;
- typedef unsigned int uint_type;
- typedef long int lint_type;
- typedef unsigned long int ulint_type;
- typedef short int sint_type;
- typedef unsigned short int usint_type;
- typedef long long int llint_type;
- typedef unsigned long long int ullint_type;
- typedef float flt_type;
- typedef double dbl_type;
- typedef long double ldbl_type;
+ using this_type = cnvbase;
+ using int_type = int;
+ using uint_type = unsigned int;
+ using lint_type = long int;
+ using ulint_type = unsigned long int;
+ using sint_type = short int;
+ using usint_type = unsigned short int;
+ using llint_type = long long int;
+ using ullint_type = unsigned long long int;
+ using flt_type = float;
+ using dbl_type = double;
+ using ldbl_type = long double;
// Integration of user-types via operator>>()
template<typename type_in, typename type_out>
@@ -106,13 +106,19 @@ struct boost::cnv::cnvbase
void
str_to_(string_type const& str, optional<out_type>& result_out) const
{
- cnv::range<string_type const> range (str);
+ using range_type = cnv::range<string_type const>;
+ using char_type = typename range_type::value_type;
+ range_type range (str);
+ auto is_space = [](char_type ch)
+ {
+ return std::isspace(static_cast<unsigned char>(ch));
+ };
if (skipws_)
- for (; !range.empty() && std::isspace(*range.begin()); ++range);
+ for (; !range.empty() && is_space(*range.begin()); ++range);
- if (range.empty()) return;
- if (std::isspace(*range.begin())) return;
+ if (range.empty()) return;
+ if (is_space(*range.begin())) return;
dncast().str_to(range, result_out);
}
@@ -120,7 +126,8 @@ struct boost::cnv::cnvbase
void
to_str_(in_type value_in, optional<string_type>& result_out) const
{
- typedef typename cnv::range<string_type>::value_type char_type;
+ using range_type = cnv::range<string_type>;
+ using char_type = typename range_type::value_type;
char_type buf[bufsize_];
cnv::range<char_type*> range = dncast().to_str(value_in, buf);
@@ -128,11 +135,7 @@ struct boost::cnv::cnvbase
char_type* end = range.end();
if (beg < end)
- {
- format_(buf, beg, end);
-
- result_out = string_type(beg, end);
- }
+ format_(buf, beg, end), result_out = string_type(beg, end);
}
template<typename char_type>
@@ -140,19 +143,18 @@ struct boost::cnv::cnvbase
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);
- }
+
if (width_)
{
- int const num_fillers = (std::max)(0, int(width_ - (end - beg)));
- int const num_left = adjust_ == boost::cnv::adjust::left ? 0
- : adjust_ == boost::cnv::adjust::right ? num_fillers
- : (num_fillers / 2);
- int const num_right = num_fillers - num_left;
- int const str_size = end - beg;
- bool const move = (beg < buf + num_left) // No room for left fillers
- || (buf + bufsize_ < end + num_right); // No room for right fillers
+ 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
if (move)
{
std::memmove(buf + num_left, beg, str_size * sizeof(char_type));
@@ -169,7 +171,7 @@ struct boost::cnv::cnvbase
// ULONG_MAX(8 bytes) = 18446744073709551615 (20(10) or 32(2) characters)
// double (8 bytes) max is 316 chars
- static int const bufsize_ = 1024;
+ static int const bufsize_ = 512;
int base_;
bool skipws_;
int precision_;
diff --git a/boost/convert/detail/forward.hpp b/boost/convert/detail/forward.hpp
index 0fc55c3aca..7ea7960490 100644
--- a/boost/convert/detail/forward.hpp
+++ b/boost/convert/detail/forward.hpp
@@ -6,6 +6,16 @@
#define BOOST_CONVERT_FORWARD_HPP
#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)
+//MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
+//MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
+//MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
+//MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
+//MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
+//MSVC++ 15.0 _MSC_VER == 1910 (Visual Studio 2017)
+
# pragma warning(disable: 4244)
# pragma warning(disable: 4224)
# pragma warning(disable: 4996)
@@ -30,10 +40,11 @@
#endif
#if defined(BOOST_INTEL) && (BOOST_INTEL <= 1200) /* Intel 12.0 and lower have broken SFINAE */
-# define BOOST_CONVERT_INTEL_SFINAE_BROKEN
+#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
diff --git a/boost/core/addressof.hpp b/boost/core/addressof.hpp
index 889b5825e1..0a2b46be77 100644
--- a/boost/core/addressof.hpp
+++ b/boost/core/addressof.hpp
@@ -1,162 +1,265 @@
-// Copyright (C) 2002 Brad King (brad.king@kitware.com)
-// Douglas Gregor (gregod@cs.rpi.edu)
-//
-// Copyright (C) 2002, 2008, 2013 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)
+/*
+Copyright (C) 2002 Brad King (brad.king@kitware.com)
+ Douglas Gregor (gregod@cs.rpi.edu)
-// For more information, see http://www.boost.org
+Copyright (C) 2002, 2008, 2013 Peter Dimov
+
+Copyright (C) 2017 Glen Joseph Fernandes (glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
#ifndef BOOST_CORE_ADDRESSOF_HPP
#define BOOST_CORE_ADDRESSOF_HPP
-# include <boost/config.hpp>
-# include <boost/detail/workaround.hpp>
-# include <cstddef>
+#include <boost/config.hpp>
-namespace boost
-{
+#if defined(BOOST_MSVC_FULL_VER) && BOOST_MSVC_FULL_VER >= 190024215
+#define BOOST_CORE_HAS_BUILTIN_ADDRESSOF
+#elif defined(BOOST_GCC) && BOOST_GCC >= 70000
+#define BOOST_CORE_HAS_BUILTIN_ADDRESSOF
+#elif defined(__has_builtin)
+#if __has_builtin(__builtin_addressof)
+#define BOOST_CORE_HAS_BUILTIN_ADDRESSOF
+#endif
+#endif
-namespace detail
-{
+#if defined(BOOST_CORE_HAS_BUILTIN_ADDRESSOF)
+#if defined(BOOST_NO_CXX11_CONSTEXPR)
+#define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF
+#endif
+
+namespace boost {
-template<class T> struct addr_impl_ref
+template<class T>
+BOOST_CONSTEXPR inline T*
+addressof(T& o) BOOST_NOEXCEPT
{
- T & v_;
+ return __builtin_addressof(o);
+}
- BOOST_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {}
- BOOST_FORCEINLINE operator T& () const { return v_; }
+} /* boost */
+#else
+#include <boost/detail/workaround.hpp>
+#include <cstddef>
+namespace boost {
+namespace detail {
+
+template<class T>
+class addressof_ref {
+public:
+ BOOST_FORCEINLINE addressof_ref(T& o) BOOST_NOEXCEPT
+ : o_(o) { }
+ BOOST_FORCEINLINE operator T&() const BOOST_NOEXCEPT {
+ return o_;
+ }
private:
- addr_impl_ref & operator=(const addr_impl_ref &);
+ addressof_ref& operator=(const addressof_ref&);
+ T& o_;
};
-template<class T> struct addressof_impl
-{
- static BOOST_FORCEINLINE T * f( T & v, long )
- {
- return reinterpret_cast<T*>(
- &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
+template<class T>
+struct address_of {
+ static BOOST_FORCEINLINE T* get(T& o, long) BOOST_NOEXCEPT {
+ return reinterpret_cast<T*>(&
+ const_cast<char&>(reinterpret_cast<const volatile char&>(o)));
}
-
- static BOOST_FORCEINLINE T * f( T * v, int )
- {
- return v;
+ static BOOST_FORCEINLINE T* get(T* p, int) BOOST_NOEXCEPT {
+ return p;
}
};
-#if !defined( BOOST_NO_CXX11_NULLPTR )
-
-#if !defined( BOOST_NO_CXX11_DECLTYPE ) && ( ( defined( __clang__ ) && !defined( _LIBCPP_VERSION ) ) || defined( __INTEL_COMPILER ) )
-
- typedef decltype(nullptr) addr_nullptr_t;
-
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+#if !defined(BOOST_NO_CXX11_DECLTYPE) && \
+ (defined(__INTEL_COMPILER) || \
+ (defined(__clang__) && !defined(_LIBCPP_VERSION)))
+typedef decltype(nullptr) addressof_null_t;
#else
-
- typedef std::nullptr_t addr_nullptr_t;
-
+typedef std::nullptr_t addressof_null_t;
#endif
-template<> struct addressof_impl< addr_nullptr_t >
-{
- typedef addr_nullptr_t T;
-
- static BOOST_FORCEINLINE T * f( T & v, int )
- {
- return &v;
+template<>
+struct address_of<addressof_null_t> {
+ typedef addressof_null_t type;
+ static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT {
+ return &o;
}
};
-template<> struct addressof_impl< addr_nullptr_t const >
-{
- typedef addr_nullptr_t const T;
-
- static BOOST_FORCEINLINE T * f( T & v, int )
- {
- return &v;
+template<>
+struct address_of<const addressof_null_t> {
+ typedef const addressof_null_t type;
+ static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT {
+ return &o;
}
};
-template<> struct addressof_impl< addr_nullptr_t volatile >
-{
- typedef addr_nullptr_t volatile T;
+template<>
+struct address_of<volatile addressof_null_t> {
+ typedef volatile addressof_null_t type;
+ static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT {
+ return &o;
+ }
+};
- static BOOST_FORCEINLINE T * f( T & v, int )
- {
- return &v;
+template<>
+struct address_of<const volatile addressof_null_t> {
+ typedef const volatile addressof_null_t type;
+ static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT {
+ return &o;
}
};
+#endif
+
+} /* detail */
-template<> struct addressof_impl< addr_nullptr_t const volatile >
+#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
+
+template<class T>
+BOOST_FORCEINLINE T*
+addressof(T& o) BOOST_NOEXCEPT
{
- typedef addr_nullptr_t const volatile T;
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) || \
+ BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120)
+ return detail::address_of<T>::get(o, 0);
+#else
+ return detail::address_of<T>::get(detail::addressof_ref<T>(o), 0);
+#endif
+}
- static BOOST_FORCEINLINE T * f( T & v, int )
- {
- return &v;
- }
+#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
+namespace detail {
+
+template<class T>
+struct addressof_result {
+ typedef T* type;
};
+} /* detail */
+
+template<class T, std::size_t N>
+BOOST_FORCEINLINE typename detail::addressof_result<T[N]>::type
+addressof(T (&o)[N]) BOOST_NOEXCEPT
+{
+ return &o;
+}
#endif
-} // namespace detail
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+template<class T, std::size_t N>
+BOOST_FORCEINLINE
+T (*addressof(T (&o)[N]) BOOST_NOEXCEPT)[N]
+{
+ return reinterpret_cast<T(*)[N]>(&o);
+}
-template<class T>
+template<class T, std::size_t N>
BOOST_FORCEINLINE
-T * addressof( T & v )
+const T (*addressof(const T (&o)[N]) BOOST_NOEXCEPT)[N]
{
-#if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || (defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120))
+ return reinterpret_cast<const T(*)[N]>(&o);
+}
+#endif
+#else
+namespace detail {
- return boost::detail::addressof_impl<T>::f( v, 0 );
+template<class T>
+T&& addressof_declval() BOOST_NOEXCEPT;
-#else
+template<class>
+struct addressof_void {
+ typedef void type;
+};
- return boost::detail::addressof_impl<T>::f( boost::detail::addr_impl_ref<T>( v ), 0 );
+template<class T, class E = void>
+struct addressof_member_operator {
+ static constexpr bool value = false;
+};
+
+template<class T>
+struct addressof_member_operator<T, typename
+ addressof_void<decltype(addressof_declval<T&>().operator&())>::type> {
+ static constexpr bool value = true;
+};
+
+#if BOOST_WORKAROUND(BOOST_INTEL, < 1600)
+struct addressof_addressable { };
+addressof_addressable*
+operator&(addressof_addressable&) BOOST_NOEXCEPT;
#endif
-}
-#if defined( __SUNPRO_CC ) && BOOST_WORKAROUND( __SUNPRO_CC, BOOST_TESTED_AT( 0x590 ) )
+template<class T, class E = void>
+struct addressof_non_member_operator {
+ static constexpr bool value = false;
+};
-namespace detail
-{
+template<class T>
+struct addressof_non_member_operator<T, typename
+ addressof_void<decltype(operator&(addressof_declval<T&>()))>::type> {
+ static constexpr bool value = true;
+};
-template<class T> struct addressof_addp
-{
- typedef T * type;
+template<class T, class E = void>
+struct addressof_expression {
+ static constexpr bool value = false;
+};
+
+template<class T>
+struct addressof_expression<T,
+ typename addressof_void<decltype(&addressof_declval<T&>())>::type> {
+ static constexpr bool value = true;
+};
+
+template<class T>
+struct addressof_is_constexpr {
+ static constexpr bool value = addressof_expression<T>::value &&
+ !addressof_member_operator<T>::value &&
+ !addressof_non_member_operator<T>::value;
};
-} // namespace detail
+template<bool E, class T>
+struct addressof_if { };
+
+template<class T>
+struct addressof_if<true, T> {
+ typedef T* type;
+};
-template< class T, std::size_t N >
+template<class T>
BOOST_FORCEINLINE
-typename detail::addressof_addp< T[N] >::type addressof( T (&t)[N] )
+typename addressof_if<!addressof_is_constexpr<T>::value, T>::type
+addressof(T& o) BOOST_NOEXCEPT
{
- return &t;
+ return address_of<T>::get(addressof_ref<T>(o), 0);
}
-#endif
-
-// Borland doesn't like casting an array reference to a char reference
-// but these overloads work around the problem.
-#if defined( __BORLANDC__ ) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-template<typename T,std::size_t N>
-BOOST_FORCEINLINE
-T (*addressof(T (&t)[N]))[N]
+template<class T>
+constexpr BOOST_FORCEINLINE
+typename addressof_if<addressof_is_constexpr<T>::value, T>::type
+addressof(T& o) BOOST_NOEXCEPT
{
- return reinterpret_cast<T(*)[N]>(&t);
+ return &o;
}
-template<typename T,std::size_t N>
-BOOST_FORCEINLINE
-const T (*addressof(const T (&t)[N]))[N]
+} /* detail */
+
+template<class T>
+constexpr BOOST_FORCEINLINE T*
+addressof(T& o) BOOST_NOEXCEPT
{
- return reinterpret_cast<const T(*)[N]>(&t);
+ return detail::addressof(o);
}
#endif
-} // namespace boost
+} /* boost */
+#endif
-#endif // BOOST_CORE_ADDRESSOF_HPP
+#endif
diff --git a/boost/core/demangle.hpp b/boost/core/demangle.hpp
index f13c26a7f4..dc714d806c 100644
--- a/boost/core/demangle.hpp
+++ b/boost/core/demangle.hpp
@@ -93,15 +93,10 @@ inline void demangle_free( char const * name ) BOOST_NOEXCEPT
inline std::string demangle( char const * name )
{
scoped_demangled_name demangled_name( name );
- char const * const p = demangled_name.get();
- if( p )
- {
- return p;
- }
- else
- {
- return name;
- }
+ char const * p = demangled_name.get();
+ if( !p )
+ p = name;
+ return p;
}
#else
diff --git a/boost/core/lightweight_test.hpp b/boost/core/lightweight_test.hpp
index d6db024250..b580dd2fa6 100644
--- a/boost/core/lightweight_test.hpp
+++ b/boost/core/lightweight_test.hpp
@@ -19,10 +19,12 @@
// http://www.boost.org/LICENSE_1_0.txt
//
+#include <iterator>
#include <boost/assert.hpp>
#include <boost/current_function.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <iostream>
+#include <cstring>
// IDE's like Visual Studio perform better if output goes to std::cout or
// some other stream, so allow user to configure output stream:
@@ -101,6 +103,16 @@ inline void throw_failed_impl(char const * excep, char const * file, int line, c
# pragma GCC diagnostic ignored "-Wsign-compare"
#endif
+// specialize test output for char pointers to avoid printing as cstring
+template <class T> inline const T& test_output_impl(const T& v) { return v; }
+inline const void* test_output_impl(const char* v) { return v; }
+inline const void* test_output_impl(const unsigned char* v) { return v; }
+inline const void* test_output_impl(const signed char* v) { return v; }
+inline const void* test_output_impl(char* v) { return v; }
+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); }
+
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 )
{
@@ -113,7 +125,7 @@ template<class T, class U> inline void test_eq_impl( char const * expr1, char co
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< file << "(" << line << "): test '" << expr1 << " == " << expr2
<< "' failed in function '" << function << "': "
- << "'" << t << "' != '" << u << "'" << std::endl;
+ << "'" << test_output_impl(t) << "' != '" << test_output_impl(u) << "'" << std::endl;
++test_errors();
}
}
@@ -130,11 +142,182 @@ template<class T, class U> inline void test_ne_impl( char const * expr1, char co
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 )
+{
+ if( std::strcmp(t, u) == 0 )
+ {
+ report_errors_remind();
+ }
+ else
+ {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << file << "(" << line << "): test '" << expr1 << " == " << expr2
+ << "' failed in function '" << function << "': "
+ << "'" << t << "' != '" << u << "'" << std::endl;
+ ++test_errors();
+ }
+}
+
+inline void test_cstr_ne_impl( char const * expr1, char const * expr2,
+ char const * file, int line, char const * function, char const * const t, char const * const u )
+{
+ if( std::strcmp(t, u) != 0 )
+ {
+ report_errors_remind();
+ }
+ else
+ {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << file << "(" << line << "): test '" << expr1 << " == " << expr2
+ << "' failed in function '" << function << "': "
<< "'" << t << "' == '" << u << "'" << std::endl;
++test_errors();
}
}
+template<class FormattedOutputFunction, class InputIterator1, class InputIterator2>
+void test_all_eq_impl(FormattedOutputFunction& output,
+ char const * file, int line, char const * function,
+ InputIterator1 first_begin, InputIterator1 first_end,
+ InputIterator2 second_begin, InputIterator2 second_end)
+{
+ InputIterator1 first_it = first_begin;
+ InputIterator2 second_it = second_begin;
+ typename std::iterator_traits<InputIterator1>::difference_type first_index = 0;
+ typename std::iterator_traits<InputIterator2>::difference_type second_index = 0;
+ std::size_t error_count = 0;
+ const std::size_t max_count = 8;
+ do
+ {
+ while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it))
+ {
+ ++first_it;
+ ++second_it;
+ ++first_index;
+ ++second_index;
+ }
+ if ((first_it == first_end) || (second_it == second_end))
+ {
+ break; // do-while
+ }
+ if (error_count == 0)
+ {
+ output << file << "(" << line << "): Container contents differ in function '" << function << "':";
+ }
+ else if (error_count >= max_count)
+ {
+ output << " ...";
+ break;
+ }
+ output << " [" << first_index << "] '" << test_output_impl(*first_it) << "' != '" << test_output_impl(*second_it) << "'";
+ ++first_it;
+ ++second_it;
+ ++first_index;
+ ++second_index;
+ ++error_count;
+ } while (first_it != first_end);
+
+ first_index += std::distance(first_it, first_end);
+ second_index += std::distance(second_it, second_end);
+ if (first_index != second_index)
+ {
+ if (error_count == 0)
+ {
+ output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")";
+ }
+ else
+ {
+ output << " [*] size(" << first_index << ") != size(" << second_index << ")";
+ }
+ ++error_count;
+ }
+
+ if (error_count == 0)
+ {
+ boost::detail::report_errors_remind();
+ }
+ else
+ {
+ output << std::endl;
+ ++boost::detail::test_errors();
+ }
+}
+
+template<class FormattedOutputFunction, class InputIterator1, class InputIterator2, typename BinaryPredicate>
+void test_all_with_impl(FormattedOutputFunction& output,
+ char const * file, int line, char const * function,
+ InputIterator1 first_begin, InputIterator1 first_end,
+ InputIterator2 second_begin, InputIterator2 second_end,
+ BinaryPredicate predicate)
+{
+ InputIterator1 first_it = first_begin;
+ InputIterator2 second_it = second_begin;
+ typename std::iterator_traits<InputIterator1>::difference_type first_index = 0;
+ typename std::iterator_traits<InputIterator2>::difference_type second_index = 0;
+ std::size_t error_count = 0;
+ const std::size_t max_count = 8;
+ do
+ {
+ while ((first_it != first_end) && (second_it != second_end) && predicate(*first_it, *second_it))
+ {
+ ++first_it;
+ ++second_it;
+ ++first_index;
+ ++second_index;
+ }
+ if ((first_it == first_end) || (second_it == second_end))
+ {
+ break; // do-while
+ }
+ if (error_count == 0)
+ {
+ output << file << "(" << line << "): Container contents differ in function '" << function << "':";
+ }
+ else if (error_count >= max_count)
+ {
+ output << " ...";
+ break;
+ }
+ output << " [" << first_index << "]";
+ ++first_it;
+ ++second_it;
+ ++first_index;
+ ++second_index;
+ ++error_count;
+ } while (first_it != first_end);
+
+ first_index += std::distance(first_it, first_end);
+ second_index += std::distance(second_it, second_end);
+ if (first_index != second_index)
+ {
+ if (error_count == 0)
+ {
+ output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")";
+ }
+ else
+ {
+ output << " [*] size(" << first_index << ") != size(" << second_index << ")";
+ }
+ ++error_count;
+ }
+
+ if (error_count == 0)
+ {
+ report_errors_remind();
+ }
+ else
+ {
+ output << std::endl;
+ ++test_errors();
+ }
+}
+
#if defined(_MSC_VER)
# pragma warning(pop)
#elif defined(__clang__) && defined(__has_warning)
@@ -177,6 +360,12 @@ 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_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) )
+
+#define BOOST_TEST_ALL_EQ(begin1, end1, begin2, end2) ( ::boost::detail::test_all_eq_impl(BOOST_LIGHTWEIGHT_TEST_OSTREAM, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, begin1, end1, begin2, end2) )
+#define BOOST_TEST_ALL_WITH(begin1, end1, begin2, end2, predicate) ( ::boost::detail::test_all_with_impl(BOOST_LIGHTWEIGHT_TEST_OSTREAM, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, begin1, end1, begin2, end2, predicate) )
+
#ifndef BOOST_NO_EXCEPTIONS
#define BOOST_TEST_THROWS( EXPR, EXCEP ) \
try { \
diff --git a/boost/coroutine2/detail/config.hpp b/boost/coroutine2/detail/config.hpp
index cfb95846a5..307ee4e78a 100644
--- a/boost/coroutine2/detail/config.hpp
+++ b/boost/coroutine2/detail/config.hpp
@@ -18,7 +18,6 @@
#if (defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES2_DYN_LINK) ) && ! defined(BOOST_COROUTINES2_STATIC_LINK)
# if defined(BOOST_COROUTINES2_SOURCE)
# define BOOST_COROUTINES2_DECL BOOST_SYMBOL_EXPORT
-# define BOOST_COROUTINES2_BUILD_DLL
# else
# define BOOST_COROUTINES2_DECL BOOST_SYMBOL_IMPORT
# endif
@@ -29,7 +28,7 @@
#endif
#if ! defined(BOOST_COROUTINES2_SOURCE) && ! defined(BOOST_ALL_NO_LIB) && ! defined(BOOST_COROUTINES2_NO_LIB)
-# define BOOST_LIB_NAME boost_coroutine
+# define BOOST_LIB_NAME boost_coroutine2
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES2_DYN_LINK)
# define BOOST_DYN_LINK
# endif
diff --git a/boost/coroutine2/detail/coroutine.hpp b/boost/coroutine2/detail/coroutine.hpp
index 7c1483d3be..1170590183 100644
--- a/boost/coroutine2/detail/coroutine.hpp
+++ b/boost/coroutine2/detail/coroutine.hpp
@@ -34,8 +34,8 @@ class push_coroutine;
# 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_ecv2.hpp>
-# include <boost/coroutine2/detail/push_control_block_ecv2.hpp>
+# 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>
@@ -45,8 +45,8 @@ class push_coroutine;
# 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_ecv2.ipp>
-# include <boost/coroutine2/detail/push_control_block_ecv2.ipp>
+# include <boost/coroutine2/detail/pull_control_block_cc.ipp>
+# include <boost/coroutine2/detail/push_control_block_cc.ipp>
# endif
#endif
diff --git a/boost/coroutine2/detail/forced_unwind.hpp b/boost/coroutine2/detail/forced_unwind.hpp
index 0f67f79a5f..d486ed43dd 100644
--- a/boost/coroutine2/detail/forced_unwind.hpp
+++ b/boost/coroutine2/detail/forced_unwind.hpp
@@ -12,8 +12,6 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
-#include <boost/context/execution_context.hpp>
-
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
diff --git a/boost/coroutine2/detail/pull_control_block_ecv2.hpp b/boost/coroutine2/detail/pull_control_block_cc.hpp
index 58d248833a..44a14e2102 100644
--- a/boost/coroutine2/detail/pull_control_block_ecv2.hpp
+++ b/boost/coroutine2/detail/pull_control_block_cc.hpp
@@ -1,5 +1,5 @@
-// Copyright Oliver Kowalke 2014.
+// Copyright Oliver Kowalke 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)
@@ -11,7 +11,7 @@
#include <type_traits>
#include <boost/config.hpp>
-#include <boost/context/execution_context.hpp>
+#include <boost/context/continuation.hpp>
#include <boost/coroutine2/detail/state.hpp>
@@ -25,7 +25,7 @@ namespace detail {
template< typename T >
struct pull_coroutine< T >::control_block {
- boost::context::execution_context< T * > ctx;
+ boost::context::continuation c;
typename push_coroutine< T >::control_block * other;
state_t state;
std::exception_ptr except;
@@ -37,7 +37,7 @@ struct pull_coroutine< T >::control_block {
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
- control_block( typename push_coroutine< T >::control_block *, boost::context::execution_context< T * > &) noexcept;
+ control_block( typename push_coroutine< T >::control_block *, boost::context::continuation &) noexcept;
~control_block();
@@ -48,7 +48,9 @@ struct pull_coroutine< T >::control_block {
void resume();
- void set( T *);
+ void set( T const&);
+ void set( T &&);
+ void reset();
T & get() noexcept;
@@ -57,18 +59,27 @@ struct pull_coroutine< T >::control_block {
template< typename T >
struct pull_coroutine< T & >::control_block {
- boost::context::execution_context< T * > ctx;
- typename push_coroutine< T & >::control_block * other;
- state_t state;
- std::exception_ptr except;
- T * t;
+ struct holder {
+ T & t;
+
+ holder( T & t_) :
+ t{ t_ } {
+ }
+ };
+
+ boost::context::continuation c;
+ typename push_coroutine< T & >::control_block * other;
+ state_t state;
+ std::exception_ptr except;
+ bool bvalid;
+ typename std::aligned_storage< sizeof( holder), alignof( holder) >::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< T * > &) noexcept;
+ control_block( typename push_coroutine< T & >::control_block *, boost::context::continuation &) noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
@@ -77,13 +88,16 @@ struct pull_coroutine< T & >::control_block {
void resume();
+ void set( T &);
+ void reset();
+
T & get() noexcept;
bool valid() const noexcept;
};
struct pull_coroutine< void >::control_block {
- boost::context::execution_context< void > ctx;
+ boost::context::continuation c;
push_coroutine< void >::control_block * other;
state_t state;
std::exception_ptr except;
@@ -93,7 +107,7 @@ struct pull_coroutine< void >::control_block {
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
- control_block( push_coroutine< void >::control_block *, boost::context::execution_context< void > &) noexcept;
+ control_block( push_coroutine< void >::control_block *, boost::context::continuation &) noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
diff --git a/boost/coroutine2/detail/pull_control_block_cc.ipp b/boost/coroutine2/detail/pull_control_block_cc.ipp
new file mode 100644
index 0000000000..0406202016
--- /dev/null
+++ b/boost/coroutine2/detail/pull_control_block_cc.ipp
@@ -0,0 +1,452 @@
+
+// Copyright Oliver Kowalke 2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
+#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
+
+#include <algorithm>
+#include <exception>
+#include <memory>
+#include <tuple>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/continuation.hpp>
+
+#include <boost/coroutine2/detail/config.hpp>
+#include <boost/coroutine2/detail/forced_unwind.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::continuation c = std::move( cb->c);
+ // destroy control structure
+ cb->~control_block();
+ // destroy coroutine's stack
+ cb->state |= state_t::destroy;
+ c.resume();
+}
+
+template< typename T >
+template< typename StackAllocator, typename Fn >
+pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+ c{},
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{},
+ bvalid{ false },
+ storage{} {
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ c = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< T >::control_block synthesized_cb{ this, c };
+ 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 ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back
+ return other->c.resume();
+ },
+ std::forward< Fn >( fn) ) );
+#else
+ c = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ [this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< T >::control_block synthesized_cb{ this, c };
+ 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 ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back
+ return other->c.resume();
+ });
+#endif
+ if ( c.data_available() ) {
+ set( c.get_data< T >() );
+ }
+}
+
+template< typename T >
+pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
+ boost::context::continuation & c_) noexcept :
+ c{ std::move( c_) },
+ other{ cb },
+ state{ state_t::none },
+ except{},
+ bvalid{ false },
+ storage{} {
+}
+
+template< typename T >
+pull_coroutine< T >::control_block::~control_block() {
+ // destroy data if 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() {
+ c = c.resume();
+ if ( c.data_available() ) {
+ set( c.get_data< T >() );
+ } else {
+ reset();
+ }
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+void
+pull_coroutine< T >::control_block::set( T const& t) {
+ // destroy data if set
+ if ( bvalid) {
+ reinterpret_cast< T * >( std::addressof( storage) )->~T();
+ }
+ ::new ( static_cast< void * >( std::addressof( storage) ) ) T( t);
+ bvalid = true;
+}
+
+template< typename T >
+void
+pull_coroutine< T >::control_block::set( T && t) {
+ // destroy data if set
+ if ( bvalid) {
+ reinterpret_cast< T * >( std::addressof( storage) )->~T();
+ }
+ ::new ( static_cast< void * >( std::addressof( storage) ) ) T( std::move( t) );
+ bvalid = true;
+}
+
+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) );
+}
+
+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::continuation c = std::move( cb->c);
+ // destroy control structure
+ cb->~control_block();
+ // destroy coroutine's stack
+ cb->state |= state_t::destroy;
+ c.resume();
+}
+
+template< typename T >
+template< typename StackAllocator, typename Fn >
+pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+ c{},
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{},
+ bvalid{ false },
+ storage{} {
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ c = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
+ // create synthesized push_coroutine< T & >
+ typename push_coroutine< T & >::control_block synthesized_cb{ this, c };
+ 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 ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back
+ return other->c.resume();
+ },
+ std::forward< Fn >( fn) ) );
+#else
+ c = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ [this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
+ // create synthesized push_coroutine< T & >
+ typename push_coroutine< T & >::control_block synthesized_cb{ this, c };
+ 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 ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back
+ return other->c.resume();
+ });
+#endif
+ if ( c.data_available() ) {
+ set( c.get_data< T & >() );
+ }
+}
+
+template< typename T >
+pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
+ boost::context::continuation & c_) noexcept :
+ c{ std::move( c_) },
+ other{ cb },
+ state{ state_t::none },
+ except{},
+ bvalid{ false },
+ storage{} {
+}
+
+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() {
+ c = c.resume();
+ if ( c.data_available() ) {
+ set( c.get_data< T & >() );
+ } else {
+ reset();
+ }
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+void
+pull_coroutine< T & >::control_block::set( T & t) {
+ ::new ( static_cast< void * >( std::addressof( storage) ) ) holder{ t };
+ bvalid = true;
+}
+
+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;
+}
+
+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< void >
+
+inline
+void
+pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::continuation c = std::move( cb->c);
+ // destroy control structure
+ cb->~control_block();
+ // destroy coroutine's stack
+ cb->state |= state_t::destroy;
+ c.resume();
+}
+
+template< typename StackAllocator, typename Fn >
+pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+ c{},
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{} {
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ c = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
+ // create synthesized push_coroutine< void >
+ typename push_coroutine< void >::control_block synthesized_cb{ this, c };
+ 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 ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back
+ return other->c.resume();
+ },
+ std::forward< Fn >( fn) ) );
+#else
+ c = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::continuation && c) mutable {
+ // create synthesized push_coroutine< void >
+ typename push_coroutine< void >::control_block synthesized_cb{ this, c };
+ 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 ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ return other->c.resume();
+ });
+#endif
+}
+
+inline
+pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
+ boost::context::continuation & c_) noexcept :
+ c{ std::move( c_) },
+ other{ cb },
+ state{ state_t::none },
+ except{} {
+}
+
+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() {
+ c = c.resume();
+ 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/pull_control_block_ecv1.ipp b/boost/coroutine2/detail/pull_control_block_ecv1.ipp
index eb2ae2778f..77866041fe 100644
--- a/boost/coroutine2/detail/pull_control_block_ecv1.ipp
+++ b/boost/coroutine2/detail/pull_control_block_ecv1.ipp
@@ -20,6 +20,7 @@
#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
@@ -46,9 +47,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
Fn && fn) :
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
ctx{ std::allocator_arg, palloc, salloc,
- std::move(
- std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void *) mutable noexcept {
+ 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 };
@@ -72,8 +71,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
},
std::forward< Fn >( fn),
- boost::context::execution_context::current(),
- std::placeholders::_1))},
+ 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 {
@@ -197,9 +195,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
Fn && fn) :
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
ctx{ std::allocator_arg, palloc, salloc,
- std::move(
- std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void *) mutable noexcept {
+ 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 };
@@ -223,8 +219,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
},
std::forward< Fn >( fn),
- boost::context::execution_context::current(),
- std::placeholders::_1))},
+ 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 {
@@ -326,9 +321,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
Fn && fn) :
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
ctx{ std::allocator_arg, palloc, salloc,
- std::move(
- std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void *) mutable noexcept {
+ 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 };
@@ -352,8 +345,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
},
std::forward< Fn >( fn),
- boost::context::execution_context::current(),
- std::placeholders::_1))},
+ 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 {
diff --git a/boost/coroutine2/detail/pull_control_block_ecv2.ipp b/boost/coroutine2/detail/pull_control_block_ecv2.ipp
deleted file mode 100644
index a1c7c93cd0..0000000000
--- a/boost/coroutine2/detail/pull_control_block_ecv2.ipp
+++ /dev/null
@@ -1,422 +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 <algorithm>
-#include <exception>
-#include <memory>
-#include <tuple>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-
-#include <boost/context/execution_context.hpp>
-
-#include <boost/coroutine2/detail/config.hpp>
-#include <boost/coroutine2/detail/forced_unwind.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< T * > ctx = std::move( cb->ctx);
- // destroy control structure
- cb->~control_block();
- // destroy coroutine's stack
- cb->state |= state_t::destroy;
- ctx( nullptr);
-}
-
-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,
- std::move(
- std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > && ctx, T *) mutable {
- // 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 ( boost::context::detail::forced_unwind const&) {
- throw;
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- auto result = other->ctx( nullptr);
- other->ctx = std::move( std::get< 0 >( result) );
- return std::move( other->ctx);
- },
- std::forward< Fn >( fn),
- std::placeholders::_1,
- std::placeholders::_2))},
-#else
- ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > && ctx, T *) mutable {
- // 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 ( boost::context::detail::forced_unwind const&) {
- throw;
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- auto result = other->ctx( nullptr);
- other->ctx = std::move( std::get< 0 >( result) );
- return std::move( other->ctx);
- }},
-#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
- resume();
-}
-
-template< typename T >
-pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
- boost::context::execution_context< T * > & ctx_) noexcept :
- ctx{ std::move( ctx_) },
- other{ cb },
- state{ state_t::none },
- except{},
- bvalid{ false },
- storage{} {
-}
-
-template< typename T >
-pull_coroutine< T >::control_block::~control_block() {
- // destroy data if 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() {
- auto result = ctx( nullptr);
- ctx = std::move( std::get< 0 >( result) );
- set( std::get< 1 >( result) );
- if ( except) {
- std::rethrow_exception( except);
- }
-}
-
-template< typename T >
-void
-pull_coroutine< T >::control_block::set( T * t) {
- // destroy data if 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< T * > ctx = std::move( cb->ctx);
- // destroy control structure
- cb->~control_block();
- // destroy coroutine's stack
- cb->state |= state_t::destroy;
- ctx( nullptr);
-}
-
-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,
- std::move(
- std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T *> && ctx, T *) mutable {
- // 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 ( boost::context::detail::forced_unwind const&) {
- throw;
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- auto result = other->ctx( nullptr);
- other->ctx = std::move( std::get< 0 >( result) );
- return std::move( other->ctx);
- },
- std::forward< Fn >( fn),
- std::placeholders::_1,
- std::placeholders::_2))},
-#else
- ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > && ctx, T *) mutable {
- // 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 ( boost::context::detail::forced_unwind const&) {
- throw;
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- auto result = other->ctx( nullptr);
- other->ctx = std::move( std::get< 0 >( result) );
- return std::move( other->ctx);
- }},
-#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
- resume();
-}
-
-template< typename T >
-pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
- boost::context::execution_context< T * > & ctx_) noexcept :
- ctx{ std::move( ctx_) },
- other{ cb },
- state{ state_t::none },
- except{},
- t{ nullptr } {
-}
-
-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() {
- auto result = ctx( nullptr);
- ctx = std::move( std::get< 0 >( result) );
- t = std::get< 1 >( result);
- if ( except) {
- std::rethrow_exception( except);
- }
-}
-
-template< typename T >
-T &
-pull_coroutine< T & >::control_block::get() noexcept {
- return * 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< void > ctx = std::move( cb->ctx);
- // destroy control structure
- cb->~control_block();
- // destroy coroutine's stack
- cb->state |= state_t::destroy;
- ctx();
-}
-
-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,
- std::move(
- std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< void > && ctx) mutable {
- // create synthesized push_coroutine< void >
- 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 ( boost::context::detail::forced_unwind const&) {
- throw;
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx = other->ctx();
- return std::move( other->ctx);
- },
- std::forward< Fn >( fn),
- std::placeholders::_1))},
-#else
- ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< void > && ctx) mutable {
- // create synthesized push_coroutine< void >
- 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 ( boost::context::detail::forced_unwind const&) {
- throw;
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx = other->ctx();
- return std::move( other->ctx);
- }},
-#endif
- other{ nullptr },
- state{ state_t::unwind },
- except{} {
- // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
- resume();
-}
-
-inline
-pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
- boost::context::execution_context< void > & ctx_) noexcept :
- ctx{ std::move( ctx_) },
- other{ cb },
- state{ state_t::none },
- except{} {
-}
-
-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() {
- ctx = 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/pull_coroutine.hpp b/boost/coroutine2/detail/pull_coroutine.hpp
index b97bdc3e9c..f4c40733bb 100644
--- a/boost/coroutine2/detail/pull_coroutine.hpp
+++ b/boost/coroutine2/detail/pull_coroutine.hpp
@@ -92,7 +92,7 @@ public:
typedef typename iterator::pointer pointer_t;
typedef typename iterator::reference reference_t;
- constexpr iterator() noexcept = default;
+ iterator() noexcept = default;
explicit iterator( pull_coroutine< T > * c) noexcept :
c_{ c } {
@@ -204,7 +204,7 @@ public:
typedef typename iterator::pointer pointer_t;
typedef typename iterator::reference reference_t;
- constexpr iterator() noexcept = default;
+ iterator() noexcept = default;
explicit iterator( pull_coroutine< T & > * c) noexcept :
c_{ c } {
diff --git a/boost/coroutine2/detail/push_control_block_ecv2.hpp b/boost/coroutine2/detail/push_control_block_cc.hpp
index feb5e4a61c..d01c98f089 100644
--- a/boost/coroutine2/detail/push_control_block_ecv2.hpp
+++ b/boost/coroutine2/detail/push_control_block_cc.hpp
@@ -10,7 +10,7 @@
#include <exception>
#include <boost/config.hpp>
-#include <boost/context/execution_context.hpp>
+#include <boost/context/continuation.hpp>
#include <boost/coroutine2/detail/state.hpp>
@@ -24,7 +24,7 @@ namespace detail {
template< typename T >
struct push_coroutine< T >::control_block {
- boost::context::execution_context< T * > ctx;
+ boost::context::continuation c;
typename pull_coroutine< T >::control_block * other;
state_t state;
std::exception_ptr except;
@@ -34,7 +34,7 @@ struct push_coroutine< T >::control_block {
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
- control_block( typename pull_coroutine< T >::control_block *, boost::context::execution_context< T * > &) noexcept;
+ control_block( typename pull_coroutine< T >::control_block *, boost::context::continuation &) noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
@@ -50,7 +50,7 @@ struct push_coroutine< T >::control_block {
template< typename T >
struct push_coroutine< T & >::control_block {
- boost::context::execution_context< T * > ctx;
+ boost::context::continuation c;
typename pull_coroutine< T & >::control_block * other;
state_t state;
std::exception_ptr except;
@@ -60,7 +60,7 @@ struct push_coroutine< T & >::control_block {
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
- control_block( typename pull_coroutine< T & >::control_block *, boost::context::execution_context< T * > &) noexcept;
+ control_block( typename pull_coroutine< T & >::control_block *, boost::context::continuation &) noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
@@ -73,7 +73,7 @@ struct push_coroutine< T & >::control_block {
};
struct push_coroutine< void >::control_block {
- boost::context::execution_context< void > ctx;
+ boost::context::continuation c;
pull_coroutine< void >::control_block * other;
state_t state;
std::exception_ptr except;
@@ -83,7 +83,7 @@ struct push_coroutine< void >::control_block {
template< typename StackAllocator, typename Fn >
control_block( context::preallocated, StackAllocator, Fn &&);
- control_block( pull_coroutine< void >::control_block *, boost::context::execution_context< void > &) noexcept;
+ control_block( pull_coroutine< void >::control_block *, boost::context::continuation &) noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
diff --git a/boost/coroutine2/detail/push_control_block_cc.ipp b/boost/coroutine2/detail/push_control_block_cc.ipp
new file mode 100644
index 0000000000..9972c7039f
--- /dev/null
+++ b/boost/coroutine2/detail/push_control_block_cc.ipp
@@ -0,0 +1,400 @@
+
+// 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 <memory>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/continuation.hpp>
+
+#include <boost/coroutine2/detail/config.hpp>
+#include <boost/coroutine2/detail/forced_unwind.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::continuation c = std::move( cb->c);
+ // destroy control structure
+ cb->~control_block();
+ // destroy coroutine's stack
+ cb->state |= state_t::destroy;
+ c.resume();
+}
+
+template< typename T >
+template< typename StackAllocator, typename Fn >
+push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+ c{},
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{} {
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ c = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
+ // create synthesized pull_coroutine< T >
+ typename pull_coroutine< T >::control_block synthesized_cb{ this, c };
+ 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_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back
+ return other->c.resume();
+ },
+ std::forward< Fn >( fn) ) );
+#else
+ c = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ [this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
+ // create synthesized pull_coroutine< T >
+ typename pull_coroutine< T >::control_block synthesized_cb{ this, c };
+ 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_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back
+ return other->c.resume();
+ });
+#endif
+}
+
+template< typename T >
+push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
+ boost::context::continuation & c_) noexcept :
+ c{ std::move( c_) },
+ other{ cb },
+ state{ state_t::none },
+ except{} {
+}
+
+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& data) {
+ // pass an pointer to other context
+ c = c.resume( data);
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+void
+push_coroutine< T >::control_block::resume( T && data) {
+ // pass an pointer to other context
+ c = c.resume( std::move( data) );
+ 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::continuation c = std::move( cb->c);
+ // destroy control structure
+ cb->~control_block();
+ // destroy coroutine's stack
+ cb->state |= state_t::destroy;
+ c.resume();
+}
+
+template< typename T >
+template< typename StackAllocator, typename Fn >
+push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+ c{},
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{} {
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ c = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
+ // create synthesized pull_coroutine< T & >
+ typename pull_coroutine< T & >::control_block synthesized_cb{ this, c };
+ 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_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back
+ return other->c.resume();
+ },
+ std::forward< Fn >( fn) ) );
+#else
+ c = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ [this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
+ // create synthesized pull_coroutine< T & >
+ typename pull_coroutine< T & >::control_block synthesized_cb{ this, c };
+ 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_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back
+ return other->c.resume();
+ });
+#endif
+}
+
+template< typename T >
+push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
+ boost::context::continuation & c_) noexcept :
+ c{ std::move( c_) },
+ other{ cb },
+ state{ state_t::none },
+ except{} {
+}
+
+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) {
+ // pass an pointer to other context
+ c = c.resume( std::ref( 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::continuation c = std::move( cb->c);
+ // destroy control structure
+ cb->~control_block();
+ // destroy coroutine's stack
+ cb->state |= state_t::destroy;
+ c.resume();
+}
+
+template< typename StackAllocator, typename Fn >
+push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn) :
+ c{},
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{} {
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ c = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
+ // create synthesized pull_coroutine< void >
+ typename pull_coroutine< void >::control_block synthesized_cb{ this, c };
+ pull_coroutine< void > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ other->c = other->c.resume();
+ if ( state_t::none == ( state & state_t::destroy) ) {
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back
+ return other->c.resume();
+ },
+ std::forward< Fn >( fn) ) );
+#else
+ c = boost::context::callcc(
+ std::allocator_arg, palloc, salloc,
+ [this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
+ // create synthesized pull_coroutine< void >
+ typename pull_coroutine< void >::control_block synthesized_cb{ this, c};
+ pull_coroutine< void > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ other->c = other->c.resume();
+ if ( state_t::none == ( state & state_t::destroy) ) {
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back
+ return other->c.resume();
+ });
+#endif
+}
+
+inline
+push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
+ boost::context::continuation & c_) noexcept :
+ c{ std::move( c_) },
+ other{ cb },
+ state{ state_t::none },
+ except{} {
+}
+
+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() {
+ c = c.resume();
+ 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/push_control_block_ecv1.ipp b/boost/coroutine2/detail/push_control_block_ecv1.ipp
index cc9622dfbe..8b4ae3fb04 100644
--- a/boost/coroutine2/detail/push_control_block_ecv1.ipp
+++ b/boost/coroutine2/detail/push_control_block_ecv1.ipp
@@ -21,6 +21,7 @@
#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
@@ -47,9 +48,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
Fn && fn) :
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
ctx{ std::allocator_arg, palloc, salloc,
- std::move(
- std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void * vp) mutable noexcept {
+ 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 };
@@ -77,8 +76,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
},
std::forward< Fn >( fn),
- boost::context::execution_context::current(),
- std::placeholders::_1))},
+ 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 {
@@ -189,9 +187,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
Fn && fn) :
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
ctx{ std::allocator_arg, palloc, salloc,
- std::move(
- std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void * vp) mutable noexcept {
+ 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 };
@@ -219,8 +215,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
},
std::forward< Fn >( fn),
- boost::context::execution_context::current(),
- std::placeholders::_1))},
+ 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 {
@@ -318,9 +313,7 @@ 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,
- std::move(
- std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx,
+ 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 };
@@ -347,8 +340,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
},
std::forward< Fn >( fn),
- boost::context::execution_context::current(),
- std::placeholders::_1))},
+ 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 {
diff --git a/boost/coroutine2/detail/push_control_block_ecv2.ipp b/boost/coroutine2/detail/push_control_block_ecv2.ipp
deleted file mode 100644
index 7ed6c572e1..0000000000
--- a/boost/coroutine2/detail/push_control_block_ecv2.ipp
+++ /dev/null
@@ -1,392 +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 <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/forced_unwind.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< T * > ctx = std::move( cb->ctx);
- // destroy control structure
- cb->~control_block();
- // destroy coroutine's stack
- cb->state |= state_t::destroy;
- ctx( nullptr);
-}
-
-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,
- std::move(
- std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > && ctx, T * data) mutable {
- // create synthesized pull_coroutine< T >
- typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
- pull_coroutine< T > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- // set transferred value
- synthesized_cb.set( data);
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( boost::context::detail::forced_unwind const&) {
- throw;
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- auto result = other->ctx( nullptr);
- other->ctx = std::move( std::get< 0 >( result) );
- return std::move( other->ctx);
- },
- std::forward< Fn >( fn),
- std::placeholders::_1,
- std::placeholders::_2))},
-#else
- ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > && ctx, T * data) mutable {
- // create synthesized pull_coroutine< T >
- typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
- pull_coroutine< T > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- // set transferred value
- synthesized_cb.set( data);
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( boost::context::detail::forced_unwind const&) {
- throw;
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- auto result = other->ctx( nullptr);
- other->ctx = std::move( std::get< 0 >( result) );
- return std::move( other->ctx);
- }},
-#endif
- other{ nullptr },
- state{ state_t::unwind },
- except{} {
-}
-
-template< typename T >
-push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
- boost::context::execution_context< T * > & ctx_) noexcept :
- ctx{ std::move( ctx_) },
- other{ cb },
- state{ state_t::none },
- except{} {
-}
-
-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& data) {
- // pass an pointer to other context
- auto result = ctx( const_cast< T * >( & data) );
- ctx = std::move( std::get< 0 >( result) );
- if ( except) {
- std::rethrow_exception( except);
- }
-}
-
-template< typename T >
-void
-push_coroutine< T >::control_block::resume( T && data) {
- // pass an pointer to other context
- auto result = ctx( std::addressof( data) );
- ctx = std::move( std::get< 0 >( result) );
- 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< T * > ctx = std::move( cb->ctx);
- // destroy control structure
- cb->~control_block();
- // destroy coroutine's stack
- cb->state |= state_t::destroy;
- ctx( nullptr);
-}
-
-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,
- std::move(
- std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > && ctx, T * data) mutable {
- // create synthesized pull_coroutine< T & >
- typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
- pull_coroutine< T & > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- // set transferred value
- synthesized_cb.t = data;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( boost::context::detail::forced_unwind const&) {
- throw;
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- auto result = other->ctx( nullptr);
- other->ctx = std::move( std::get< 0 >( result) );
- return std::move( other->ctx);
- },
- std::forward< Fn >( fn),
- std::placeholders::_1,
- std::placeholders::_2))},
-#else
- ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > && ctx, T * data) mutable {
- // create synthesized pull_coroutine< T & >
- typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
- pull_coroutine< T & > synthesized{ & synthesized_cb };
- other = & synthesized_cb;
- // set transferred value
- synthesized_cb.t = data;
- if ( state_t::none == ( state & state_t::destroy) ) {
- try {
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( boost::context::detail::forced_unwind const&) {
- throw;
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- auto result = other->ctx( nullptr);
- other->ctx = std::move( std::get< 0 >( result) );
- return std::move( other->ctx);
- }},
-#endif
- other{ nullptr },
- state{ state_t::unwind },
- except{} {
-}
-
-template< typename T >
-push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
- boost::context::execution_context< T * > & ctx_) noexcept :
- ctx{ std::move( ctx_) },
- other{ cb },
- state{ state_t::none },
- except{} {
-}
-
-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) {
- // pass an pointer to other context
- auto result = ctx( const_cast< typename std::remove_const< T >::type * >( std::addressof( t) ) );
- ctx = std::move( std::get< 0 >( result) );
- 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< void > ctx = std::move( cb->ctx);
- // destroy control structure
- cb->~control_block();
- // destroy coroutine's stack
- cb->state |= state_t::destroy;
- ctx();
-}
-
-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,
- std::move(
- std::bind(
- [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< void > && ctx) mutable {
- // create synthesized pull_coroutine< void >
- 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 {
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( boost::context::detail::forced_unwind const&) {
- throw;
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx = other->ctx();
- return std::move( other->ctx);
- },
- std::forward< Fn >( fn),
- std::placeholders::_1))},
-#else
- ctx{ std::allocator_arg, palloc, salloc,
- [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< void > && ctx) mutable {
- // create synthesized pull_coroutine< void >
- 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 {
- auto fn = std::move( fn_);
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( boost::context::detail::forced_unwind const&) {
- throw;
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- }
- // set termination flags
- state |= state_t::complete;
- // jump back to ctx
- other->ctx = other->ctx();
- return std::move( other->ctx);
- }},
-#endif
- other{ nullptr },
- state{ state_t::unwind },
- except{} {
-}
-
-inline
-push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
- boost::context::execution_context< void > & ctx_) noexcept :
- ctx{ std::move( ctx_) },
- other{ cb },
- state{ state_t::none },
- except{} {
-}
-
-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() {
- ctx = 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/push_coroutine.hpp b/boost/coroutine2/detail/push_coroutine.hpp
index 1b62663ab7..533d4f930f 100644
--- a/boost/coroutine2/detail/push_coroutine.hpp
+++ b/boost/coroutine2/detail/push_coroutine.hpp
@@ -72,14 +72,14 @@ public:
push_coroutine< T > * c_{ nullptr };
public:
- constexpr iterator() noexcept = default;
+ iterator() noexcept = default;
explicit iterator( push_coroutine< T > * c) noexcept :
c_{ c } {
}
iterator & operator=( T t) {
- BOOST_ASSERT( c_);
+ BOOST_ASSERT( nullptr != c_);
if ( ! ( * c_)( t) ) {
c_ = nullptr;
}
@@ -150,14 +150,14 @@ public:
push_coroutine< T & > * c_{ nullptr };
public:
- constexpr iterator() noexcept = default;
+ iterator() noexcept = default;
explicit iterator( push_coroutine< T & > * c) noexcept :
c_{ c } {
}
iterator & operator=( T & t) {
- BOOST_ASSERT( c_);
+ BOOST_ASSERT( nullptr != c_);
if ( ! ( * c_)( t) ) {
c_ = nullptr;
}
diff --git a/boost/coroutine2/detail/wrap.hpp b/boost/coroutine2/detail/wrap.hpp
new file mode 100644
index 0000000000..25abce3b61
--- /dev/null
+++ b/boost/coroutine2/detail/wrap.hpp
@@ -0,0 +1,112 @@
+
+// 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_COROUTINE2_DETAIL_WRAP_H
+#define BOOST_COROUTINE2_DETAIL_WRAP_H
+
+#include <type_traits>
+
+#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/fiber/detail/config.hpp>
+#include <boost/fiber/detail/data.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+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:
+ typename std::decay< Fn1 >::type fn1_;
+ typename std::decay< Fn2 >::type fn2_;
+
+public:
+ wrapper( Fn1 && fn1, Fn2 && fn2) :
+ fn1_( std::move( fn1) ),
+ fn2_( std::move( fn2) ) {
+ }
+
+ 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) {
+ return boost::context::detail::invoke(
+ std::move( fn1_),
+ fn2_,
+ std::forward< boost::context::continuation >( c) );
+ }
+};
+
+template< typename Fn1, typename Fn2 >
+wrapper< Fn1, Fn2 >
+wrap( Fn1 && fn1, Fn2 && fn2) {
+ return wrapper< Fn1, Fn2 >(
+ std::forward< Fn1 >( fn1),
+ std::forward< Fn2 >( fn2) );
+}
+#endif
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINE2_DETAIL_WRAP_H
diff --git a/boost/date_time/c_time.hpp b/boost/date_time/c_time.hpp
index 5998908c4e..0b07a1b283 100644
--- a/boost/date_time/c_time.hpp
+++ b/boost/date_time/c_time.hpp
@@ -57,15 +57,15 @@ namespace date_time {
static std::tm* localtime(const std::time_t* t, std::tm* result)
{
// localtime_r() not in namespace std???
- #if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
- std::tm tmp;
- if(!localtime_r(t,&tmp))
+#if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
+ std::tm tmp;
+ if(!localtime_r(t,&tmp))
result = 0;
- else
- *result = tmp;
- #else
+ else
+ *result = tmp;
+#else
result = localtime_r(t, result);
- #endif
+#endif
if (!result)
boost::throw_exception(std::runtime_error("could not convert calendar time to local time"));
return result;
@@ -75,15 +75,15 @@ namespace date_time {
static std::tm* gmtime(const std::time_t* t, std::tm* result)
{
// gmtime_r() not in namespace std???
- #if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
- std::tm tmp;
- if(!gmtime_r(t,&tmp))
+#if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
+ std::tm tmp;
+ if(!gmtime_r(t,&tmp))
result = 0;
else
- *result = tmp;
- #else
+ *result = tmp;
+#else
result = gmtime_r(t, result);
- #endif
+#endif
if (!result)
boost::throw_exception(std::runtime_error("could not convert calendar time to UTC time"));
return result;
diff --git a/boost/date_time/constrained_value.hpp b/boost/date_time/constrained_value.hpp
index 910e99a861..b1122d76d8 100644
--- a/boost/date_time/constrained_value.hpp
+++ b/boost/date_time/constrained_value.hpp
@@ -39,7 +39,7 @@ namespace CV {
*
*/
template<class value_policies>
- class constrained_value {
+ class BOOST_SYMBOL_VISIBLE constrained_value {
public:
typedef typename value_policies::value_type value_type;
// typedef except_type exception_type;
@@ -80,9 +80,9 @@ namespace CV {
//! Template to shortcut the constrained_value policy creation process
template<typename rep_type, rep_type min_value,
rep_type max_value, class exception_type>
- class simple_exception_policy
+ class BOOST_SYMBOL_VISIBLE simple_exception_policy
{
- struct exception_wrapper : public exception_type
+ struct BOOST_SYMBOL_VISIBLE exception_wrapper : public exception_type
{
// In order to support throw_exception mechanism in the BOOST_NO_EXCEPTIONS mode,
// we'll have to provide a way to acquire std::exception from the exception being thrown.
diff --git a/boost/date_time/date.hpp b/boost/date_time/date.hpp
index b38db220d5..18333fd3ff 100644
--- a/boost/date_time/date.hpp
+++ b/boost/date_time/date.hpp
@@ -10,6 +10,7 @@
*/
#include <boost/operators.hpp>
+#include <boost/date_time/compiler_config.hpp>
#include <boost/date_time/year_month_day.hpp>
#include <boost/date_time/special_defs.hpp>
@@ -50,7 +51,7 @@ namespace date_time {
template<class T, class calendar, class duration_type_>
- class date : private
+ class BOOST_SYMBOL_VISIBLE date : private
boost::less_than_comparable<T
, boost::equality_comparable<T
> >
diff --git a/boost/date_time/date_duration.hpp b/boost/date_time/date_duration.hpp
index f5b4b083d7..22a05ed123 100644
--- a/boost/date_time/date_duration.hpp
+++ b/boost/date_time/date_duration.hpp
@@ -12,6 +12,7 @@
#include <boost/operators.hpp>
#include <boost/date_time/special_defs.hpp>
+#include <boost/date_time/compiler_config.hpp>
namespace boost {
namespace date_time {
@@ -19,7 +20,7 @@ namespace date_time {
//! Duration type with date level resolution
template<class duration_rep_traits>
- class date_duration : private
+ class BOOST_SYMBOL_VISIBLE date_duration : private
boost::less_than_comparable1< date_duration< duration_rep_traits >
, boost::equality_comparable1< date_duration< duration_rep_traits >
, boost::addable1< date_duration< duration_rep_traits >
@@ -121,7 +122,7 @@ namespace date_time {
/*! Struct for instantiating date_duration with <b>NO</b> special values
* functionality. Allows for transparent implementation of either
* date_duration<long> or date_duration<int_adapter<long> > */
- struct duration_traits_long
+ struct BOOST_SYMBOL_VISIBLE duration_traits_long
{
typedef long int_type;
typedef long impl_type;
@@ -131,7 +132,7 @@ namespace date_time {
/*! Struct for instantiating date_duration <b>WITH</b> special values
* functionality. Allows for transparent implementation of either
* date_duration<long> or date_duration<int_adapter<long> > */
- struct duration_traits_adapted
+ struct BOOST_SYMBOL_VISIBLE duration_traits_adapted
{
typedef long int_type;
typedef boost::date_time::int_adapter<long> impl_type;
diff --git a/boost/date_time/date_duration_types.hpp b/boost/date_time/date_duration_types.hpp
index 8c0e9860d0..7271d0191a 100644
--- a/boost/date_time/date_duration_types.hpp
+++ b/boost/date_time/date_duration_types.hpp
@@ -8,7 +8,8 @@
* Author: Jeff Garland, Bart Garst
* $Date$
*/
-
+
+#include <boost/date_time/compiler_config.hpp>
#include <boost/date_time/int_adapter.hpp>
#include <boost/date_time/special_defs.hpp>
#include <boost/date_time/date_duration.hpp>
@@ -19,7 +20,7 @@ namespace date_time {
//! Additional duration type that represents a number of n*7 days
template <class duration_config>
- class weeks_duration : public date_duration<duration_config> {
+ class BOOST_SYMBOL_VISIBLE weeks_duration : public date_duration<duration_config> {
public:
weeks_duration(typename duration_config::impl_type w)
: date_duration<duration_config>(w * 7) {}
@@ -29,7 +30,7 @@ namespace date_time {
// predeclare
template<class t>
- class years_duration;
+ class BOOST_SYMBOL_VISIBLE years_duration;
//! additional duration type that represents a logical month
/*! A logical month enables things like: "date(2002,Mar,2) + months(2) ->
@@ -37,7 +38,7 @@ namespace date_time {
* also be a last-day-of-the-month.
*/
template<class base_config>
- class months_duration
+ class BOOST_SYMBOL_VISIBLE months_duration
{
private:
typedef typename base_config::int_rep int_rep;
@@ -159,7 +160,7 @@ namespace date_time {
* 2004-Feb-29).
*/
template<class base_config>
- class years_duration
+ class BOOST_SYMBOL_VISIBLE years_duration
{
private:
typedef typename base_config::int_rep int_rep;
diff --git a/boost/date_time/date_facet.hpp b/boost/date_time/date_facet.hpp
index c3574cc953..df7d53b6c9 100644
--- a/boost/date_time/date_facet.hpp
+++ b/boost/date_time/date_facet.hpp
@@ -46,7 +46,7 @@ namespace boost { namespace date_time {
template <class date_type,
class CharT,
class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
- class date_facet : public std::locale::facet {
+ class BOOST_SYMBOL_VISIBLE date_facet : public std::locale::facet {
public:
typedef typename date_type::duration_type duration_type;
// greg_weekday is gregorian_calendar::day_of_week_type
@@ -408,7 +408,7 @@ namespace boost { namespace date_time {
template <class date_type,
class CharT,
class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > >
- class date_input_facet : public std::locale::facet {
+ class BOOST_SYMBOL_VISIBLE date_input_facet : public std::locale::facet {
public:
typedef typename date_type::duration_type duration_type;
// greg_weekday is gregorian_calendar::day_of_week_type
diff --git a/boost/date_time/date_names_put.hpp b/boost/date_time/date_names_put.hpp
index e055fa8734..20da2d2ed0 100644
--- a/boost/date_time/date_names_put.hpp
+++ b/boost/date_time/date_names_put.hpp
@@ -10,14 +10,15 @@
*/
-#include "boost/date_time/locale_config.hpp" // set BOOST_DATE_TIME_NO_LOCALE
+#include <boost/date_time/locale_config.hpp> // set BOOST_DATE_TIME_NO_LOCALE
#ifndef BOOST_DATE_TIME_NO_LOCALE
-#include "boost/date_time/special_defs.hpp"
-#include "boost/date_time/date_defs.hpp"
-#include "boost/date_time/parse_format_base.hpp"
-#include "boost/lexical_cast.hpp"
+#include <boost/date_time/compiler_config.hpp>
+#include <boost/date_time/special_defs.hpp>
+#include <boost/date_time/date_defs.hpp>
+#include <boost/date_time/parse_format_base.hpp>
+#include <boost/lexical_cast.hpp>
#include <locale>
@@ -39,7 +40,7 @@ namespace date_time {
template<class Config,
class charT = char,
class OutputIterator = std::ostreambuf_iterator<charT> >
- class date_names_put : public std::locale::facet
+ class BOOST_SYMBOL_VISIBLE date_names_put : public std::locale::facet
{
public:
date_names_put() {}
@@ -208,7 +209,7 @@ namespace date_time {
template<class Config,
class charT = char,
class OutputIterator = std::ostreambuf_iterator<charT> >
- class all_date_names_put : public date_names_put<Config, charT, OutputIterator>
+ class BOOST_SYMBOL_VISIBLE all_date_names_put : public date_names_put<Config, charT, OutputIterator>
{
public:
all_date_names_put(const charT* const month_short_names[],
diff --git a/boost/date_time/gregorian/greg_calendar.hpp b/boost/date_time/gregorian/greg_calendar.hpp
index 34ce0aec47..16e47c1df4 100644
--- a/boost/date_time/gregorian/greg_calendar.hpp
+++ b/boost/date_time/gregorian/greg_calendar.hpp
@@ -10,6 +10,7 @@
*/
#include <boost/cstdint.hpp>
+#include <boost/date_time/compiler_config.hpp>
#include <boost/date_time/gregorian/greg_weekday.hpp>
#include <boost/date_time/gregorian/greg_day_of_year.hpp>
#include <boost/date_time/gregorian_calendar.hpp>
@@ -23,7 +24,7 @@ namespace gregorian {
typedef date_time::int_adapter<uint32_t> fancy_date_rep;
//! Gregorian calendar for this implementation, hard work in the base
- class gregorian_calendar :
+ class BOOST_SYMBOL_VISIBLE gregorian_calendar :
public date_time::gregorian_calendar_base<greg_year_month_day, fancy_date_rep::int_type> {
public:
//! Type to hold a weekday (eg: Sunday, Monday,...)
diff --git a/boost/date_time/gregorian/greg_date.hpp b/boost/date_time/gregorian/greg_date.hpp
index f7aa2fc5f1..4f56bedf1a 100644
--- a/boost/date_time/gregorian/greg_date.hpp
+++ b/boost/date_time/gregorian/greg_date.hpp
@@ -10,6 +10,7 @@
*/
#include <boost/throw_exception.hpp>
+#include <boost/date_time/compiler_config.hpp>
#include <boost/date_time/date.hpp>
#include <boost/date_time/special_defs.hpp>
#include <boost/date_time/gregorian/greg_calendar.hpp>
@@ -34,7 +35,7 @@ namespace gregorian {
supported.
\ingroup date_basics
*/
- class date : public date_time::date<date, gregorian_calendar, date_duration>
+ class BOOST_SYMBOL_VISIBLE date : public date_time::date<date, gregorian_calendar, date_duration>
{
public:
typedef gregorian_calendar::year_type year_type;
diff --git a/boost/date_time/gregorian/greg_day.hpp b/boost/date_time/gregorian/greg_day.hpp
index 4a2d5e7e46..8cadc6c7e5 100644
--- a/boost/date_time/gregorian/greg_day.hpp
+++ b/boost/date_time/gregorian/greg_day.hpp
@@ -9,7 +9,8 @@
* $Date$
*/
-#include "boost/date_time/constrained_value.hpp"
+#include <boost/date_time/constrained_value.hpp>
+#include <boost/date_time/compiler_config.hpp>
#include <stdexcept>
#include <string>
@@ -17,7 +18,7 @@ namespace boost {
namespace gregorian {
//! Exception type for gregorian day of month (1..31)
- struct bad_day_of_month : public std::out_of_range
+ struct BOOST_SYMBOL_VISIBLE bad_day_of_month : public std::out_of_range
{
bad_day_of_month() :
std::out_of_range(std::string("Day of month value is out of range 1..31"))
@@ -39,7 +40,7 @@ namespace gregorian {
is automatically range checked so values outside of the range 1-31
will cause a bad_day_of_month exception
*/
- class greg_day : public greg_day_rep {
+ class BOOST_SYMBOL_VISIBLE greg_day : public greg_day_rep {
public:
greg_day(unsigned short day_of_month) : greg_day_rep(day_of_month) {}
unsigned short as_number() const {return value_;}
diff --git a/boost/date_time/gregorian/greg_day_of_year.hpp b/boost/date_time/gregorian/greg_day_of_year.hpp
index abf0c9eeb3..3f753e1d6a 100644
--- a/boost/date_time/gregorian/greg_day_of_year.hpp
+++ b/boost/date_time/gregorian/greg_day_of_year.hpp
@@ -9,7 +9,8 @@
* $Date$
*/
-#include "boost/date_time/constrained_value.hpp"
+#include <boost/date_time/constrained_value.hpp>
+#include <boost/date_time/compiler_config.hpp>
#include <stdexcept>
#include <string>
@@ -17,7 +18,7 @@ namespace boost {
namespace gregorian {
//! Exception type for day of year (1..366)
- struct bad_day_of_year : public std::out_of_range
+ struct BOOST_SYMBOL_VISIBLE bad_day_of_year : public std::out_of_range
{
bad_day_of_year() :
std::out_of_range(std::string("Day of year value is out of range 1..366"))
diff --git a/boost/date_time/gregorian/greg_duration.hpp b/boost/date_time/gregorian/greg_duration.hpp
index dc6ad60755..3b1a497818 100644
--- a/boost/date_time/gregorian/greg_duration.hpp
+++ b/boost/date_time/gregorian/greg_duration.hpp
@@ -9,6 +9,7 @@
* $Date$
*/
+#include <boost/date_time/compiler_config.hpp>
#include <boost/date_time/date_duration.hpp>
#include <boost/date_time/int_adapter.hpp>
#include <boost/date_time/special_defs.hpp>
@@ -22,7 +23,7 @@ namespace gregorian {
//! Durations in days for gregorian system
/*! \ingroup date_basics
*/
- class date_duration :
+ class BOOST_SYMBOL_VISIBLE date_duration :
public boost::date_time::date_duration< date_duration_rep >
{
typedef boost::date_time::date_duration< date_duration_rep > base_type;
diff --git a/boost/date_time/gregorian/greg_duration_types.hpp b/boost/date_time/gregorian/greg_duration_types.hpp
index d1f9a65f97..e6611e680c 100644
--- a/boost/date_time/gregorian/greg_duration_types.hpp
+++ b/boost/date_time/gregorian/greg_duration_types.hpp
@@ -1,6 +1,6 @@
#ifndef GREG_DURATION_TYPES_HPP___
#define GREG_DURATION_TYPES_HPP___
-
+
/* Copyright (c) 2004 CrystalClear Software, Inc.
* Subject to Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
@@ -9,6 +9,7 @@
*/
+#include <boost/date_time/compiler_config.hpp>
#include <boost/date_time/gregorian/greg_date.hpp>
#include <boost/date_time/int_adapter.hpp>
#include <boost/date_time/adjust_functors.hpp>
@@ -19,7 +20,7 @@ namespace boost {
namespace gregorian {
//! config struct for additional duration types (ie months_duration<> & years_duration<>)
- struct greg_durations_config {
+ struct BOOST_SYMBOL_VISIBLE greg_durations_config {
typedef date date_type;
typedef date_time::int_adapter<int> int_rep;
typedef date_time::month_functor<date_type> month_adjustor_type;
@@ -28,7 +29,7 @@ namespace gregorian {
typedef date_time::months_duration<greg_durations_config> months;
typedef date_time::years_duration<greg_durations_config> years;
- class weeks_duration : public date_duration {
+ class BOOST_SYMBOL_VISIBLE weeks_duration : public date_duration {
public:
weeks_duration(duration_rep w)
: date_duration(w * 7) {}
diff --git a/boost/date_time/gregorian/greg_facet.hpp b/boost/date_time/gregorian/greg_facet.hpp
index 624c96e1ed..f720aac3bf 100644
--- a/boost/date_time/gregorian/greg_facet.hpp
+++ b/boost/date_time/gregorian/greg_facet.hpp
@@ -9,9 +9,10 @@
* $Date$
*/
-#include "boost/date_time/gregorian/gregorian_types.hpp"
-#include "boost/date_time/date_formatting_locales.hpp" // sets BOOST_DATE_TIME_NO_LOCALE
-#include "boost/date_time/gregorian/parsers.hpp"
+#include <boost/date_time/compiler_config.hpp>
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include <boost/date_time/date_formatting_locales.hpp> // sets BOOST_DATE_TIME_NO_LOCALE
+#include <boost/date_time/gregorian/parsers.hpp>
//This file is basically commented out if locales are not supported
#ifndef BOOST_DATE_TIME_NO_LOCALE
@@ -26,7 +27,7 @@ namespace boost {
namespace gregorian {
//! Configuration of the output facet template
- struct greg_facet_config
+ struct BOOST_SYMBOL_VISIBLE greg_facet_config
{
typedef boost::gregorian::greg_month month_type;
typedef boost::date_time::special_values special_value_enum;
@@ -365,8 +366,7 @@ namespace gregorian {
} } //namespace gregorian
-#endif
-
-
+#endif
+
#endif
diff --git a/boost/date_time/gregorian/greg_month.hpp b/boost/date_time/gregorian/greg_month.hpp
index d483f77424..d46343353f 100644
--- a/boost/date_time/gregorian/greg_month.hpp
+++ b/boost/date_time/gregorian/greg_month.hpp
@@ -9,10 +9,10 @@
* $Date$
*/
-#include "boost/date_time/constrained_value.hpp"
-#include "boost/date_time/date_defs.hpp"
-#include "boost/shared_ptr.hpp"
-#include "boost/date_time/compiler_config.hpp"
+#include <boost/date_time/constrained_value.hpp>
+#include <boost/date_time/date_defs.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/compiler_config.hpp>
#include <stdexcept>
#include <string>
#include <map>
@@ -41,7 +41,7 @@ namespace gregorian {
using date_time::NumMonths;
//! Exception thrown if a greg_month is constructed with a value out of range
- struct bad_month : public std::out_of_range
+ struct BOOST_SYMBOL_VISIBLE bad_month : public std::out_of_range
{
bad_month() : std::out_of_range(std::string("Month number is out of range 1..12")) {}
};
diff --git a/boost/date_time/gregorian/greg_weekday.hpp b/boost/date_time/gregorian/greg_weekday.hpp
index 60fec32297..263ef5df99 100644
--- a/boost/date_time/gregorian/greg_weekday.hpp
+++ b/boost/date_time/gregorian/greg_weekday.hpp
@@ -9,9 +9,9 @@
* $Date$
*/
-#include "boost/date_time/constrained_value.hpp"
-#include "boost/date_time/date_defs.hpp"
-#include "boost/date_time/compiler_config.hpp"
+#include <boost/date_time/constrained_value.hpp>
+#include <boost/date_time/date_defs.hpp>
+#include <boost/date_time/compiler_config.hpp>
#include <stdexcept>
#include <string>
@@ -29,7 +29,7 @@ namespace gregorian {
//! Exception that flags that a weekday number is incorrect
- struct bad_weekday : public std::out_of_range
+ struct BOOST_SYMBOL_VISIBLE bad_weekday : public std::out_of_range
{
bad_weekday() : std::out_of_range(std::string("Weekday is out of range 0..6")) {}
};
diff --git a/boost/date_time/gregorian/greg_year.hpp b/boost/date_time/gregorian/greg_year.hpp
index 3d98fd06b2..ebcb49e206 100644
--- a/boost/date_time/gregorian/greg_year.hpp
+++ b/boost/date_time/gregorian/greg_year.hpp
@@ -9,7 +9,8 @@
* $Date$
*/
-#include "boost/date_time/constrained_value.hpp"
+#include <boost/date_time/compiler_config.hpp>
+#include <boost/date_time/constrained_value.hpp>
#include <stdexcept>
#include <string>
@@ -17,7 +18,7 @@ namespace boost {
namespace gregorian {
//! Exception type for gregorian year
- struct bad_year : public std::out_of_range
+ struct BOOST_SYMBOL_VISIBLE bad_year : public std::out_of_range
{
bad_year() :
std::out_of_range(std::string("Year is out of valid range: 1400..10000"))
@@ -36,12 +37,10 @@ namespace gregorian {
at the moment, but they are the limits of current testing of the
library. As such they may be increased in the future.
*/
- class greg_year : public greg_year_rep {
+ class BOOST_SYMBOL_VISIBLE greg_year : public greg_year_rep {
public:
greg_year(unsigned short year) : greg_year_rep(year) {}
operator unsigned short() const {return value_;}
- private:
-
};
diff --git a/boost/date_time/gregorian_calendar.hpp b/boost/date_time/gregorian_calendar.hpp
index dfe3771aab..0478592941 100644
--- a/boost/date_time/gregorian_calendar.hpp
+++ b/boost/date_time/gregorian_calendar.hpp
@@ -9,6 +9,7 @@
* $Date$
*/
+#include <boost/date_time/compiler_config.hpp>
namespace boost {
namespace date_time {
@@ -25,7 +26,7 @@ namespace date_time {
@param date_int_type_ Underlying type for the date count. Must be an arithmetic type.
*/
template<typename ymd_type_, typename date_int_type_>
- class gregorian_calendar_base {
+ class BOOST_SYMBOL_VISIBLE gregorian_calendar_base {
public:
//! define a type a date split into components
typedef ymd_type_ ymd_type;
diff --git a/boost/date_time/local_time/local_date_time.hpp b/boost/date_time/local_time/local_date_time.hpp
index a3762d9243..e88a231b54 100644
--- a/boost/date_time/local_time/local_date_time.hpp
+++ b/boost/date_time/local_time/local_date_time.hpp
@@ -16,6 +16,7 @@
#include <boost/throw_exception.hpp>
#include <boost/date_time/time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> //todo remove?
+#include <boost/date_time/compiler_config.hpp>
#include <boost/date_time/dst_rules.hpp>
#include <boost/date_time/time_zone_base.hpp>
#include <boost/date_time/special_defs.hpp>
@@ -25,18 +26,18 @@ namespace boost {
namespace local_time {
//! simple exception for reporting when STD or DST cannot be determined
- struct ambiguous_result : public std::logic_error
+ struct BOOST_SYMBOL_VISIBLE ambiguous_result : public std::logic_error
{
ambiguous_result (std::string const& msg = std::string()) :
std::logic_error(std::string("Daylight Savings Results are ambiguous: " + msg)) {}
};
//! simple exception for when time label given cannot exist
- struct time_label_invalid : public std::logic_error
+ struct BOOST_SYMBOL_VISIBLE time_label_invalid : public std::logic_error
{
time_label_invalid (std::string const& msg = std::string()) :
std::logic_error(std::string("Time label given is invalid: " + msg)) {}
};
- struct dst_not_valid: public std::logic_error
+ struct BOOST_SYMBOL_VISIBLE dst_not_valid: public std::logic_error
{
dst_not_valid(std::string const& msg = std::string()) :
std::logic_error(std::string("is_dst flag does not match resulting dst for time label given: " + msg)) {}
@@ -61,7 +62,7 @@ namespace local_time {
*/
template<class utc_time_=posix_time::ptime,
class tz_type=date_time::time_zone_base<utc_time_,char> >
- class local_date_time_base : public date_time::base_time<utc_time_,
+ class BOOST_SYMBOL_VISIBLE local_date_time_base : public date_time::base_time<utc_time_,
boost::posix_time::posix_time_system> {
public:
typedef utc_time_ utc_time_type;
diff --git a/boost/date_time/local_time/posix_time_zone.hpp b/boost/date_time/local_time/posix_time_zone.hpp
index d0ef31d5b8..9c2c04ba41 100644
--- a/boost/date_time/local_time/posix_time_zone.hpp
+++ b/boost/date_time/local_time/posix_time_zone.hpp
@@ -13,6 +13,7 @@
#include <stdexcept>
#include <boost/tokenizer.hpp>
#include <boost/throw_exception.hpp>
+#include <boost/date_time/compiler_config.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/time_zone_names.hpp>
#include <boost/date_time/time_zone_base.hpp>
@@ -25,13 +26,13 @@ namespace boost{
namespace local_time{
//! simple exception for UTC and Daylight savings start/end offsets
- struct bad_offset : public std::out_of_range
+ struct BOOST_SYMBOL_VISIBLE bad_offset : public std::out_of_range
{
bad_offset(std::string const& msg = std::string()) :
std::out_of_range(std::string("Offset out of range: " + msg)) {}
};
//! simple exception for UTC daylight savings adjustment
- struct bad_adjustment : public std::out_of_range
+ struct BOOST_SYMBOL_VISIBLE bad_adjustment : public std::out_of_range
{
bad_adjustment(std::string const& msg = std::string()) :
std::out_of_range(std::string("Adjustment out of range: " + msg)) {}
@@ -67,7 +68,7 @@ namespace local_time{
* http://www.worldtimezone.com/utc/utc+1200.html
*/
template<class CharT>
- class posix_time_zone_base : public date_time::time_zone_base<posix_time::ptime,CharT> {
+ class BOOST_SYMBOL_VISIBLE posix_time_zone_base : public date_time::time_zone_base<posix_time::ptime,CharT> {
public:
typedef boost::posix_time::time_duration time_duration_type;
typedef date_time::time_zone_names_base<CharT> time_zone_names;
diff --git a/boost/date_time/period.hpp b/boost/date_time/period.hpp
index 1a88209341..13011af271 100644
--- a/boost/date_time/period.hpp
+++ b/boost/date_time/period.hpp
@@ -17,7 +17,8 @@
*/
-#include "boost/operators.hpp"
+#include <boost/operators.hpp>
+#include <boost/date_time/compiler_config.hpp>
namespace boost {
@@ -48,7 +49,7 @@ namespace date_time {
*/
template<class point_rep, class duration_rep>
- class period : private
+ class BOOST_SYMBOL_VISIBLE period : private
boost::less_than_comparable<period<point_rep, duration_rep>
, boost::equality_comparable< period<point_rep, duration_rep>
> >
diff --git a/boost/date_time/posix_time/date_duration_operators.hpp b/boost/date_time/posix_time/date_duration_operators.hpp
index 60821f0c46..f3c61d7a95 100644
--- a/boost/date_time/posix_time/date_duration_operators.hpp
+++ b/boost/date_time/posix_time/date_duration_operators.hpp
@@ -1,6 +1,6 @@
#ifndef DATE_DURATION_OPERATORS_HPP___
#define DATE_DURATION_OPERATORS_HPP___
-
+
/* Copyright (c) 2004 CrystalClear Software, Inc.
* Subject to the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or
diff --git a/boost/date_time/posix_time/posix_time_config.hpp b/boost/date_time/posix_time/posix_time_config.hpp
index 60b34683fd..996afcae59 100644
--- a/boost/date_time/posix_time/posix_time_config.hpp
+++ b/boost/date_time/posix_time/posix_time_config.hpp
@@ -54,7 +54,7 @@ namespace posix_time {
//! Base time duration type
/*! \ingroup time_basics
*/
- class time_duration :
+ class BOOST_SYMBOL_VISIBLE time_duration :
public date_time::time_duration<time_duration, time_res_traits>
{
public:
@@ -134,7 +134,7 @@ namespace posix_time {
}
};
- class posix_time_system_config
+ class BOOST_SYMBOL_VISIBLE posix_time_system_config
{
public:
typedef simple_time_rep time_rep_type;
diff --git a/boost/date_time/posix_time/posix_time_duration.hpp b/boost/date_time/posix_time/posix_time_duration.hpp
index 34380de904..1143cedb57 100644
--- a/boost/date_time/posix_time/posix_time_duration.hpp
+++ b/boost/date_time/posix_time/posix_time_duration.hpp
@@ -9,7 +9,8 @@
* $Date$
*/
-#include "boost/date_time/posix_time/posix_time_config.hpp"
+#include <boost/date_time/compiler_config.hpp>
+#include <boost/date_time/posix_time/posix_time_config.hpp>
namespace boost {
namespace posix_time {
@@ -17,7 +18,7 @@ namespace posix_time {
//! Allows expression of durations as an hour count
/*! \ingroup time_basics
*/
- class hours : public time_duration
+ class BOOST_SYMBOL_VISIBLE hours : public time_duration
{
public:
explicit hours(long h) :
@@ -28,7 +29,7 @@ namespace posix_time {
//! Allows expression of durations as a minute count
/*! \ingroup time_basics
*/
- class minutes : public time_duration
+ class BOOST_SYMBOL_VISIBLE minutes : public time_duration
{
public:
explicit minutes(long m) :
@@ -39,7 +40,7 @@ namespace posix_time {
//! Allows expression of durations as a seconds count
/*! \ingroup time_basics
*/
- class seconds : public time_duration
+ class BOOST_SYMBOL_VISIBLE seconds : public time_duration
{
public:
explicit seconds(long s) :
diff --git a/boost/date_time/posix_time/ptime.hpp b/boost/date_time/posix_time/ptime.hpp
index e4f9d02d1f..c97edf9cfb 100644
--- a/boost/date_time/posix_time/ptime.hpp
+++ b/boost/date_time/posix_time/ptime.hpp
@@ -9,8 +9,9 @@
* $Date$
*/
-#include "boost/date_time/posix_time/posix_time_system.hpp"
-#include "boost/date_time/time.hpp"
+#include <boost/date_time/posix_time/posix_time_system.hpp>
+#include <boost/date_time/time.hpp>
+#include <boost/date_time/compiler_config.hpp>
namespace boost {
@@ -24,11 +25,11 @@ namespace posix_time {
using date_time::not_a_date_time;
using date_time::max_date_time;
using date_time::min_date_time;
-
+
//! Time type with no timezone or other adjustments
/*! \ingroup time_basics
*/
- class ptime : public date_time::base_time<ptime, posix_time_system>
+ class BOOST_SYMBOL_VISIBLE ptime : public date_time::base_time<ptime, posix_time_system>
{
public:
typedef posix_time_system time_system_type;
@@ -53,7 +54,7 @@ namespace posix_time {
ptime() : date_time::base_time<time_type,time_system_type>(gregorian::date(not_a_date_time), time_duration_type(not_a_date_time))
{}
#endif // DATE_TIME_NO_DEFAULT_CONSTRUCTOR
-
+
};
diff --git a/boost/date_time/time_duration.hpp b/boost/date_time/time_duration.hpp
index 58768bcd2d..fe4881e88b 100644
--- a/boost/date_time/time_duration.hpp
+++ b/boost/date_time/time_duration.hpp
@@ -31,7 +31,7 @@ namespace date_time {
@param rep_type The time resolution traits for this duration type.
*/
template<class T, typename rep_type>
- class time_duration : private
+ class BOOST_SYMBOL_VISIBLE time_duration : private
boost::less_than_comparable<T
, boost::equality_comparable<T
> >
@@ -265,7 +265,7 @@ namespace date_time {
* 10 for frac_of_second and resoultion adjustment
*/
template<class base_duration, boost::int64_t frac_of_second>
- class subsecond_duration : public base_duration
+ class BOOST_SYMBOL_VISIBLE subsecond_duration : public base_duration
{
public:
typedef typename base_duration::impl_type impl_type;
diff --git a/boost/date_time/time_facet.hpp b/boost/date_time/time_facet.hpp
index be6010c692..38b2ba7639 100644
--- a/boost/date_time/time_facet.hpp
+++ b/boost/date_time/time_facet.hpp
@@ -200,7 +200,7 @@ namespace date_time {
template <class time_type,
class CharT,
class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
- class time_facet :
+ class BOOST_SYMBOL_VISIBLE time_facet :
public boost::date_time::date_facet<typename time_type::date_type , CharT, OutItrT> {
typedef time_formats< CharT > formats_type;
public:
@@ -693,7 +693,7 @@ namespace date_time {
template <class time_type,
class CharT,
class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > >
- class time_input_facet :
+ class BOOST_SYMBOL_VISIBLE time_input_facet :
public boost::date_time::date_input_facet<typename time_type::date_type , CharT, InItrT> {
public:
typedef typename time_type::date_type date_type;
diff --git a/boost/date_time/time_zone_base.hpp b/boost/date_time/time_zone_base.hpp
index 576c77a223..a788429073 100644
--- a/boost/date_time/time_zone_base.hpp
+++ b/boost/date_time/time_zone_base.hpp
@@ -11,6 +11,7 @@
#include <string>
#include <sstream>
+#include <boost/date_time/compiler_config.hpp>
namespace boost {
namespace date_time {
@@ -31,7 +32,7 @@ namespace date_time {
* resource (hence the derivation from boost::counted_base.
*/
template<typename time_type, typename CharT>
- class time_zone_base {
+ class BOOST_SYMBOL_VISIBLE time_zone_base {
public:
typedef CharT char_type;
typedef std::basic_string<CharT> string_type;
diff --git a/boost/date_time/year_month_day.hpp b/boost/date_time/year_month_day.hpp
index e1bf2c7001..6355ab2711 100644
--- a/boost/date_time/year_month_day.hpp
+++ b/boost/date_time/year_month_day.hpp
@@ -9,12 +9,14 @@
* $Date$
*/
+#include <boost/date_time/compiler_config.hpp>
+
namespace boost {
namespace date_time {
//! Allow rapid creation of ymd triples of different types
template<typename YearType, typename MonthType, typename DayType>
- struct year_month_day_base {
+ struct BOOST_SYMBOL_VISIBLE year_month_day_base {
year_month_day_base(YearType year,
MonthType month,
DayType day);
diff --git a/boost/detail/lcast_precision.hpp b/boost/detail/lcast_precision.hpp
index 93abce18ce..2be88fd87f 100644
--- a/boost/detail/lcast_precision.hpp
+++ b/boost/detail/lcast_precision.hpp
@@ -125,6 +125,7 @@ inline std::streamsize lcast_get_precision(T* = 0)
limits::radix == 10 && limits::digits10 > 0;
std::streamsize const streamsize_max =
(boost::integer_traits<std::streamsize>::max)();
+ (void)streamsize_max;
if(is_specialized_bin)
{ // Floating-point types with
diff --git a/boost/detail/winapi/config.hpp b/boost/detail/winapi/config.hpp
index 1f08c2a88e..9254eb912b 100644
--- a/boost/detail/winapi/config.hpp
+++ b/boost/detail/winapi/config.hpp
@@ -54,7 +54,10 @@
#endif
#endif
-#if defined(BOOST_USE_WINDOWS_H)
+#define BOOST_DETAIL_WINAPI_MAKE_NTDDI_VERSION2(x) x##0000
+#define BOOST_DETAIL_WINAPI_MAKE_NTDDI_VERSION(x) BOOST_DETAIL_WINAPI_MAKE_NTDDI_VERSION2(x)
+
+#if defined(BOOST_USE_WINDOWS_H) || defined(BOOST_WINAPI_DEFINE_VERSION_MACROS)
// We have to define the version macros so that windows.h provides the necessary symbols
#if !defined(_WIN32_WINNT)
#define _WIN32_WINNT BOOST_USE_WINAPI_VERSION
@@ -62,6 +65,9 @@
#if !defined(WINVER)
#define WINVER BOOST_USE_WINAPI_VERSION
#endif
+#if !defined(NTDDI_VERSION)
+#define NTDDI_VERSION BOOST_DETAIL_WINAPI_MAKE_NTDDI_VERSION(BOOST_USE_WINAPI_VERSION)
+#endif
#endif
#include <boost/config.hpp>
diff --git a/boost/detail/winapi/crypt.hpp b/boost/detail/winapi/crypt.hpp
index 0650845179..95c2cf8f3c 100644
--- a/boost/detail/winapi/crypt.hpp
+++ b/boost/detail/winapi/crypt.hpp
@@ -98,10 +98,23 @@ CryptGenRandom(
boost::detail::winapi::DWORD_ dwLen,
boost::detail::winapi::BYTE_ *pbBuffer);
+#if defined(_MSC_VER) && (_MSC_VER+0) >= 1500 &&\
+ (\
+ (defined(NTDDI_VERSION) && (NTDDI_VERSION+0) < BOOST_DETAIL_WINAPI_MAKE_NTDDI_VERSION(BOOST_WINAPI_VERSION_WINXP)) ||\
+ (!defined(NTDDI_VERSION) && BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP)\
+ )
+// Standalone MS Windows SDK 6.0A and later provide a different declaration of CryptReleaseContext for Windows 2000 and older.
+// This is not the case for (a) MinGW and MinGW-w64 and (b) MSVC 7.1 and 8, which are shipped with their own Windows SDK.
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
+CryptReleaseContext(
+ boost::detail::winapi::HCRYPTPROV_ hProv,
+ boost::detail::winapi::ULONG_PTR_ dwFlags);
+#else
BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
CryptReleaseContext(
boost::detail::winapi::HCRYPTPROV_ hProv,
boost::detail::winapi::DWORD_ dwFlags);
+#endif
}
#endif // !defined( BOOST_USE_WINDOWS_H )
@@ -134,15 +147,23 @@ const DWORD_ CRYPT_SILENT_ = 64;
#endif
#if !defined( BOOST_NO_ANSI_APIS )
-using ::CryptEnumProvidersA;
using ::CryptAcquireContextA;
#endif
-using ::CryptEnumProvidersW;
using ::CryptAcquireContextW;
using ::CryptGenRandom;
-using ::CryptReleaseContext;
#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_FORCEINLINE BOOL_ CryptEnumProvidersA(
+ DWORD_ dwIndex,
+ DWORD_ *pdwReserved,
+ DWORD_ dwFlags,
+ DWORD_ *pdwProvType,
+ LPSTR_ szProvName,
+ DWORD_ *pcbProvName)
+{
+ return ::CryptEnumProvidersA(dwIndex, pdwReserved, dwFlags, pdwProvType, winapi::detail::cast_ptr(szProvName), pcbProvName);
+}
+
BOOST_FORCEINLINE BOOL_ crypt_enum_providers(
DWORD_ dwIndex,
DWORD_ *pdwReserved,
@@ -165,6 +186,17 @@ BOOST_FORCEINLINE BOOL_ crypt_acquire_context(
}
#endif
+BOOST_FORCEINLINE BOOL_ CryptEnumProvidersW(
+ DWORD_ dwIndex,
+ DWORD_ *pdwReserved,
+ DWORD_ dwFlags,
+ DWORD_ *pdwProvType,
+ LPWSTR_ szProvName,
+ DWORD_ *pcbProvName)
+{
+ return ::CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, winapi::detail::cast_ptr(szProvName), pcbProvName);
+}
+
BOOST_FORCEINLINE BOOL_ crypt_enum_providers(
DWORD_ dwIndex,
DWORD_ *pdwReserved,
@@ -186,6 +218,11 @@ BOOST_FORCEINLINE BOOL_ crypt_acquire_context(
return ::CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags);
}
+BOOST_FORCEINLINE BOOL_ CryptReleaseContext(HCRYPTPROV_ hProv, DWORD_ dwFlags)
+{
+ return ::CryptReleaseContext(hProv, dwFlags);
+}
+
}
}
}
diff --git a/boost/detail/winapi/jobs.hpp b/boost/detail/winapi/jobs.hpp
index 233df17ec4..63087a2b2a 100644
--- a/boost/detail/winapi/jobs.hpp
+++ b/boost/detail/winapi/jobs.hpp
@@ -27,10 +27,12 @@ BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI AssignProcessToJobObject
boost::detail::winapi::HANDLE_ hJob,
boost::detail::winapi::HANDLE_ hProcess);
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WINXP
BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI IsProcessInJob(
boost::detail::winapi::HANDLE_ ProcessHandle,
boost::detail::winapi::HANDLE_ JobHandle,
boost::detail::winapi::PBOOL_ Result);
+#endif
BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI TerminateJobObject(
boost::detail::winapi::HANDLE_ hJob,
@@ -73,7 +75,9 @@ using ::OpenJobObjectA;
using ::OpenJobObjectW;
using ::AssignProcessToJobObject;
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WINXP
using ::IsProcessInJob;
+#endif
using ::TerminateJobObject;
#if !defined( BOOST_NO_ANSI_APIS )
diff --git a/boost/detail/workaround.hpp b/boost/detail/workaround.hpp
index 40b3423b37..7727aaf1de 100644
--- a/boost/detail/workaround.hpp
+++ b/boost/detail/workaround.hpp
@@ -85,6 +85,11 @@
#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
diff --git a/boost/dll/detail/aggressive_ptr_cast.hpp b/boost/dll/detail/aggressive_ptr_cast.hpp
index a882cd9b19..8d1ecc112b 100644
--- a/boost/dll/detail/aggressive_ptr_cast.hpp
+++ b/boost/dll/detail/aggressive_ptr_cast.hpp
@@ -1,5 +1,5 @@
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
-// Copyright 2015-2016 Antony Polukhin.
+// Copyright 2015-2017 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
@@ -21,9 +21,12 @@
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/enable_if.hpp>
-#include <boost/cstdint.hpp> // boost::uintptr_t
#include <cstring> // std::memcpy
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ * 100 + __GNUC_MINOR__ > 301)
+# pragma GCC system_header
+#endif
+
namespace boost { namespace dll { namespace detail {
// GCC warns when reinterpret_cast between function pointer and object pointer occur.
@@ -48,11 +51,14 @@ BOOST_FORCEINLINE typename boost::disable_if_c<boost::is_member_pointer<To>::val
"Pointer to function and pointer to object differ in size on your platform."
);
- return reinterpret_cast<To>(
- reinterpret_cast<boost::uintptr_t>(v)
- );
+ return reinterpret_cast<To>(v);
}
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4172) // "returning address of local variable or temporary" but **v is not local!
+#endif
+
template <class To, class From>
BOOST_FORCEINLINE typename boost::disable_if_c<!boost::is_reference<To>::value || boost::is_member_pointer<From>::value, To>::type
aggressive_ptr_cast(From v) BOOST_NOEXCEPT
@@ -71,18 +77,17 @@ BOOST_FORCEINLINE typename boost::disable_if_c<!boost::is_reference<To>::value |
sizeof(v) == sizeof(typename boost::remove_reference<To>::type*),
"Pointer to function and pointer to object differ in size on your platform."
);
-
return static_cast<To>(
- *reinterpret_cast<typename boost::remove_reference<To>::type*>(
- *reinterpret_cast<boost::uintptr_t*>(
- reinterpret_cast<unsigned char*>(
- v
- )
- )
+ **reinterpret_cast<typename boost::remove_reference<To>::type**>(
+ v
)
);
}
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
template <class To, class From>
BOOST_FORCEINLINE typename boost::disable_if_c<!boost::is_member_pointer<To>::value || boost::is_member_pointer<From>::value, To>::type
aggressive_ptr_cast(From v) BOOST_NOEXCEPT
@@ -98,7 +103,7 @@ BOOST_FORCEINLINE typename boost::disable_if_c<!boost::is_member_pointer<To>::va
);
To res = 0;
- std::memcpy(&res, &v, sizeof(To));
+ std::memcpy(&res, &v, sizeof(From));
return res;
}
diff --git a/boost/dll/detail/demangling/msvc.hpp b/boost/dll/detail/demangling/msvc.hpp
index b5d526b581..c1abd6a185 100644
--- a/boost/dll/detail/demangling/msvc.hpp
+++ b/boost/dll/detail/demangling/msvc.hpp
@@ -185,7 +185,7 @@ namespace parser
}
template<typename Return>
- auto arg_list(const mangled_storage_impl & ms, Return (*)())
+ auto arg_list(const mangled_storage_impl& /*ms*/, Return (*)())
{
return x3::string("void");
}
diff --git a/boost/dll/detail/import_mangled_helpers.hpp b/boost/dll/detail/import_mangled_helpers.hpp
index c5942f69a8..b1a22e7012 100644
--- a/boost/dll/detail/import_mangled_helpers.hpp
+++ b/boost/dll/detail/import_mangled_helpers.hpp
@@ -71,28 +71,32 @@ template <class ...Ts>
struct function_tuple;
template <class Return, class...Args, class T2, class ...Ts>
-struct function_tuple<Return(Args...), T2, Ts...> : function_tuple<T2, Ts...>
+struct function_tuple<Return(Args...), T2, Ts...>
+ : function_tuple<T2, Ts...>
{
- constexpr function_tuple(Return(* t)(Args...), T2* t2, Ts* ... ts) : function_tuple<T2, Ts...>(t2, ts...), _f(t) {};
- Return(*_f)(Args...);
+ Return(*f_)(Args...);
- Return operator()(Args...args)
- {
- return (*_f)(static_cast<Args>(args)...);
+ constexpr function_tuple(Return(* t)(Args...), T2* t2, Ts* ... ts)
+ : function_tuple<T2, Ts...>(t2, ts...)
+ , f_(t)
+ {}
+
+ Return operator()(Args...args) const {
+ return (*f_)(static_cast<Args>(args)...);
}
using function_tuple<T2, Ts...>::operator();
-
};
template <class Return, class...Args>
-struct function_tuple<Return(Args...)>
-{
- constexpr function_tuple(Return(* t)(Args...)) : _f(t) {};
- Return(*_f)(Args...);
+struct function_tuple<Return(Args...)> {
+ Return(*f_)(Args...);
- Return operator()(Args...args)
- {
- return (*_f)(static_cast<Args>(args)...);
+ constexpr function_tuple(Return(* t)(Args...))
+ : f_(t)
+ {}
+
+ Return operator()(Args...args) const {
+ return (*f_)(static_cast<Args>(args)...);
}
};
@@ -250,33 +254,35 @@ template <class ...Ts>
struct mem_fn_tuple;
template <class Class, class Return, class...Args, class T2, class ...Ts>
-struct mem_fn_tuple<mem_fn_def<Class, Return(Args...)>, T2, Ts...> : mem_fn_tuple<T2, Ts...>
+struct mem_fn_tuple<mem_fn_def<Class, Return(Args...)>, T2, Ts...>
+ : mem_fn_tuple<T2, Ts...>
{
typedef typename boost::dll::detail::get_mem_fn_type<Class, Return(Args...)>::mem_fn mem_fn;
+ mem_fn f_;
constexpr mem_fn_tuple(mem_fn f, typename T2::mem_fn t2, typename Ts::mem_fn ... ts)
- : mem_fn_tuple<T2, Ts...>(t2, ts...), _f(f) {};
- mem_fn _f;
+ : mem_fn_tuple<T2, Ts...>(t2, ts...)
+ , f_(f)
+ {}
- Return operator()(Class* const cl, Args...args)
- {
- return (cl->*_f)(static_cast<Args>(args)...);
+ Return operator()(Class* const cl, Args...args) const {
+ return (cl->*f_)(static_cast<Args>(args)...);
}
using mem_fn_tuple<T2, Ts...>::operator();
};
template <class Class, class Return, class...Args>
-struct mem_fn_tuple<mem_fn_def<Class, Return(Args...)>>
-{
+struct mem_fn_tuple<mem_fn_def<Class, Return(Args...)>> {
typedef typename boost::dll::detail::get_mem_fn_type<Class, Return(Args...)>::mem_fn mem_fn;
+ mem_fn f_;
- constexpr mem_fn_tuple(mem_fn f) : _f(f) {};
- mem_fn _f;
+ constexpr mem_fn_tuple(mem_fn f)
+ : f_(f)
+ {}
- Return operator()(Class * const cl, Args...args)
- {
- return (cl->*_f)(static_cast<Args>(args)...);
+ Return operator()(Class * const cl, Args...args) const {
+ return (cl->*f_)(static_cast<Args>(args)...);
}
};
diff --git a/boost/dll/detail/posix/path_from_handle.hpp b/boost/dll/detail/posix/path_from_handle.hpp
index a2787623d6..65d1a78b96 100644
--- a/boost/dll/detail/posix/path_from_handle.hpp
+++ b/boost/dll/detail/posix/path_from_handle.hpp
@@ -84,12 +84,12 @@ namespace boost { namespace dll { namespace detail {
const struct soinfo* si = reinterpret_cast<const struct soinfo*>(
static_cast<const char*>(handle) + work_around_b_24465209__offset
);
- boost::filesystem::path ret = boost::dll::detail::symbol_location_impl(si->base, ec);
+ boost::filesystem::path ret = boost::dll::symbol_location_ptr(si->base, ec);
if (ec) {
ec.clear();
si = static_cast<const struct soinfo*>(handle);
- return boost::dll::detail::symbol_location_impl(si->base, ec);
+ return boost::dll::symbol_location_ptr(si->base, ec);
}
return ret;
diff --git a/boost/dll/import_mangled.hpp b/boost/dll/import_mangled.hpp
index 7463168e10..69490ed19d 100644
--- a/boost/dll/import_mangled.hpp
+++ b/boost/dll/import_mangled.hpp
@@ -34,11 +34,12 @@ namespace detail
template <class ... Ts>
class mangled_library_function {
// Copying of `boost::dll::shared_library` is very expensive, so we use a `shared_ptr` to make it faster.
- boost::shared_ptr<function_tuple<Ts...>> f_;
-
+ boost::shared_ptr<shared_library> lib_;
+ function_tuple<Ts...> f_;
public:
- inline mangled_library_function(const boost::shared_ptr<shared_library>& lib, Ts*... func_ptr) BOOST_NOEXCEPT
- : f_(lib, new function_tuple<Ts...>(func_ptr...))
+ constexpr mangled_library_function(const boost::shared_ptr<shared_library>& lib, Ts*... func_ptr) BOOST_NOEXCEPT
+ : lib_(lib)
+ , f_(func_ptr...)
{}
@@ -51,10 +52,10 @@ public:
// f(1, 2); // error: too many arguments to function
// f(); // error: too few arguments to function
template <class... Args>
- inline auto operator()(Args&&... args) const
- -> decltype( (*f_)(static_cast<Args&&>(args)...) )
+ auto operator()(Args&&... args) const
+ -> decltype( f_(static_cast<Args&&>(args)...) )
{
- return (*f_)(static_cast<Args&&>(args)...);
+ return f_(static_cast<Args&&>(args)...);
}
};
@@ -66,18 +67,20 @@ template <class Class, class ... Ts>
class mangled_library_mem_fn<Class, sequence<Ts...>> {
// Copying of `boost::dll::shared_library` is very expensive, so we use a `shared_ptr` to make it faster.
typedef mem_fn_tuple<Ts...> call_tuple_t;
- boost::shared_ptr<call_tuple_t> f_;
+ boost::shared_ptr<shared_library> lib_;
+ call_tuple_t f_;
public:
- inline mangled_library_mem_fn(const boost::shared_ptr<shared_library>& lib,
- typename Ts::mem_fn... func_ptr) BOOST_NOEXCEPT
- : f_(lib, new call_tuple_t(func_ptr...))
+ constexpr mangled_library_mem_fn(const boost::shared_ptr<shared_library>& lib, typename Ts::mem_fn... func_ptr) BOOST_NOEXCEPT
+ : lib_(lib)
+ , f_(func_ptr...)
{}
template <class ClassIn, class... Args>
- inline auto operator()(ClassIn *cl, Args&&... args) const -> decltype( (*f_)(cl, static_cast<Args&&>(args)...) )
+ auto operator()(ClassIn *cl, Args&&... args) const
+ -> decltype( f_(cl, static_cast<Args&&>(args)...) )
{
- return (*f_)(cl, static_cast<Args&&>(args)...);
+ return f_(cl, static_cast<Args&&>(args)...);
}
};
diff --git a/boost/dll/runtime_symbol_info.hpp b/boost/dll/runtime_symbol_info.hpp
index 80cce510f9..3f94e2ee1b 100644
--- a/boost/dll/runtime_symbol_info.hpp
+++ b/boost/dll/runtime_symbol_info.hpp
@@ -1,5 +1,5 @@
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
-// Copyright 2015-2016 Antony Polukhin.
+// Copyright 2015-2017 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
@@ -28,30 +28,59 @@
/// \brief Provides methods for getting acceptable by boost::dll::shared_library location of symbol, source line or program.
namespace boost { namespace dll {
-namespace detail {
#if BOOST_OS_WINDOWS
- inline boost::filesystem::path symbol_location_impl(const void* symbol, boost::system::error_code& ec) {
+namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code& ec) {
+ return boost::dll::detail::path_from_handle(NULL, ec);
+ }
+} // namespace detail
+#endif
+
+ /*!
+ * On success returns full path and name to the binary object that holds symbol pointed by ptr_to_symbol.
+ *
+ * \param ptr_to_symbol Pointer to symbol which location is to be determined.
+ * \param ec Variable that will be set to the result of the operation.
+ * \return Path to the binary object that holds symbol or empty path in case error.
+ * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept boost::system::error_code also throws boost::system::system_error.
+ *
+ * \b Examples:
+ * \code
+ * int main() {
+ * dll::symbol_location_ptr(std::set_terminate(0)); // returns "/some/path/libmy_terminate_handler.so"
+ * dll::symbol_location_ptr(::signal(SIGSEGV, SIG_DFL)); // returns "/some/path/libmy_symbol_handler.so"
+ * }
+ * \endcode
+ */
+ template <class T>
+ inline boost::filesystem::path symbol_location_ptr(T ptr_to_symbol, boost::system::error_code& ec) {
+ BOOST_STATIC_ASSERT_MSG(boost::is_pointer<T>::value, "boost::dll::symbol_location_ptr works only with pointers! `ptr_to_symbol` must be a pointer");
boost::filesystem::path ret;
+ if (!ptr_to_symbol) {
+ ec = boost::system::error_code(
+ boost::system::errc::bad_address,
+ boost::system::generic_category()
+ );
+ return ret;
+ }
+ ec.clear();
+
+ const void* ptr = boost::dll::detail::aggressive_ptr_cast<const void*>(ptr_to_symbol);
+
+#if BOOST_OS_WINDOWS
boost::detail::winapi::MEMORY_BASIC_INFORMATION_ mbi;
- if (!boost::detail::winapi::VirtualQuery(symbol, &mbi, sizeof(mbi))) {
+ if (!boost::detail::winapi::VirtualQuery(ptr, &mbi, sizeof(mbi))) {
ec = boost::dll::detail::last_error_code();
return ret;
}
return boost::dll::detail::path_from_handle(reinterpret_cast<boost::detail::winapi::HMODULE_>(mbi.AllocationBase), ec);
- }
-
- inline boost::filesystem::path program_location_impl(boost::system::error_code& ec) {
- return boost::dll::detail::path_from_handle(NULL, ec);
- }
#else
- inline boost::filesystem::path symbol_location_impl(const void* symbol, boost::system::error_code& ec) {
- boost::filesystem::path ret;
Dl_info info;
// Some of the libc headers miss `const` in `dladdr(const void*, Dl_info*)`
- const int res = dladdr(const_cast<void*>(symbol), &info);
+ const int res = dladdr(const_cast<void*>(ptr), &info);
if (res) {
ret = info.dli_fname;
@@ -64,12 +93,26 @@ namespace detail {
}
return ret;
- }
#endif
-} // namespace detail
+ }
+
+ //! \overload symbol_location_ptr(const void* ptr_to_symbol, boost::system::error_code& ec)
+ template <class T>
+ inline boost::filesystem::path symbol_location_ptr(T ptr_to_symbol) {
+ boost::filesystem::path ret;
+ boost::system::error_code ec;
+ ret = boost::dll::symbol_location_ptr(ptr_to_symbol, ec);
+
+ if (ec) {
+ boost::dll::detail::report_error(ec, "boost::dll::symbol_location_ptr(T ptr_to_symbol) failed");
+ }
+
+ return ret;
+ }
/*!
* On success returns full path and name of the binary object that holds symbol.
+ *
* \tparam T Type of the symbol, must not be explicitly specified.
* \param symbol Symbol which location is to be determined.
* \param ec Variable that will be set to the result of the operation.
@@ -93,7 +136,7 @@ namespace detail {
template <class T>
inline boost::filesystem::path symbol_location(const T& symbol, boost::system::error_code& ec) {
ec.clear();
- return boost::dll::detail::symbol_location_impl(
+ return boost::dll::symbol_location_ptr(
boost::dll::detail::aggressive_ptr_cast<const void*>(boost::addressof(symbol)),
ec
);
@@ -112,7 +155,7 @@ namespace detail {
{
boost::filesystem::path ret;
boost::system::error_code ec;
- ret = boost::dll::detail::symbol_location_impl(
+ ret = boost::dll::symbol_location_ptr(
boost::dll::detail::aggressive_ptr_cast<const void*>(boost::addressof(symbol)),
ec
);
@@ -126,7 +169,7 @@ namespace detail {
/// @cond
// We have anonymous namespace here to make sure that `this_line_location()` method is instantiated in
- // current translation module and is not shadowed by instantiations from other modules.
+ // current translation unit and is not shadowed by instantiations from other units.
namespace {
/// @endcond
diff --git a/boost/dll/smart_library.hpp b/boost/dll/smart_library.hpp
index 03bade8100..c5859251de 100644
--- a/boost/dll/smart_library.hpp
+++ b/boost/dll/smart_library.hpp
@@ -95,7 +95,7 @@ public:
//! \copydoc shared_library::shared_library(const boost::filesystem::path& lib_path, load_mode::type mode = load_mode::default_mode)
smart_library(const boost::filesystem::path& lib_path, load_mode::type mode = load_mode::default_mode) {
_lib.load(lib_path, mode);
- _storage.load(lib_path, mode);
+ _storage.load(lib_path);
}
//! \copydoc shared_library::shared_library(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode)
diff --git a/boost/dynamic_bitset/dynamic_bitset.hpp b/boost/dynamic_bitset/dynamic_bitset.hpp
index 86b5428597..05798b5262 100644
--- a/boost/dynamic_bitset/dynamic_bitset.hpp
+++ b/boost/dynamic_bitset/dynamic_bitset.hpp
@@ -348,6 +348,10 @@ public:
#endif
+public:
+ // forward declaration for optional zero-copy serialization support
+ class serialize_impl;
+ friend class serialize_impl;
private:
BOOST_STATIC_CONSTANT(block_width_type, ulong_width = std::numeric_limits<unsigned long>::digits);
diff --git a/boost/dynamic_bitset/serialization.hpp b/boost/dynamic_bitset/serialization.hpp
new file mode 100644
index 0000000000..2b59d56b02
--- /dev/null
+++ b/boost/dynamic_bitset/serialization.hpp
@@ -0,0 +1,46 @@
+// -----------------------------------------------------------
+//
+// Copyright (c) 2015 Seth Heeren
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// -----------------------------------------------------------
+
+#ifndef BOOST_DYNAMIC_BITSET_SERIALIZATION_HPP
+#define BOOST_DYNAMIC_BITSET_SERIALIZATION_HPP
+
+#include "boost/dynamic_bitset/dynamic_bitset.hpp"
+#include <boost/serialization/vector.hpp>
+
+namespace boost {
+
+ // implementation for optional zero-copy serialization support
+ template <typename Block, typename Allocator>
+ class dynamic_bitset<Block, Allocator>::serialize_impl
+ {
+ public:
+ template <typename Ar>
+ static void serialize(Ar& ar, dynamic_bitset<Block, Allocator>& bs, unsigned) {
+ ar & serialization::make_nvp("m_num_bits", bs.m_num_bits)
+ & serialization::make_nvp("m_bits", bs.m_bits);
+ }
+ };
+
+}
+
+// ADL hook to Boost Serialization library
+namespace boost {
+ namespace serialization {
+
+ template <typename Ar, typename Block, typename Allocator>
+ void serialize(Ar& ar, dynamic_bitset<Block, Allocator>& bs, unsigned version) {
+ dynamic_bitset<Block, Allocator>::serialize_impl::serialize(ar, bs, version);
+ }
+
+ } // namespace serialization
+} // namespace boost
+
+#endif // include guard
+
diff --git a/boost/fiber/algo/algorithm.hpp b/boost/fiber/algo/algorithm.hpp
index 515fc5ed5c..9b846e774b 100644
--- a/boost/fiber/algo/algorithm.hpp
+++ b/boost/fiber/algo/algorithm.hpp
@@ -43,11 +43,11 @@ struct BOOST_FIBERS_DECL algorithm {
class BOOST_FIBERS_DECL algorithm_with_properties_base : public algorithm {
public:
// called by fiber_properties::notify() -- don't directly call
- virtual void property_change_( context * f, fiber_properties * props) noexcept = 0;
+ virtual void property_change_( context * ctx, fiber_properties * props) noexcept = 0;
protected:
- static fiber_properties* get_properties( context * f) noexcept;
- static void set_properties( context * f, fiber_properties * p) noexcept;
+ static fiber_properties* get_properties( context * ctx) noexcept;
+ static void set_properties( context * ctx, fiber_properties * p) noexcept;
};
template< typename PROPS >
@@ -58,18 +58,18 @@ struct algorithm_with_properties : public algorithm_with_properties_base {
// must override awakened() with properties parameter instead. Otherwise
// you'd have to remember to start every subclass awakened() override
// with: algorithm_with_properties<PROPS>::awakened(fb);
- virtual void awakened( context * f) noexcept override final {
- fiber_properties * props = super::get_properties( f);
+ virtual void awakened( context * ctx) noexcept override final {
+ fiber_properties * props = super::get_properties( ctx);
if ( nullptr == props) {
// TODO: would be great if PROPS could be allocated on the new
// fiber's stack somehow
- props = new_properties( f);
+ props = new_properties( ctx);
// It is not good for new_properties() to return 0.
- BOOST_ASSERT_MSG(props, "new_properties() must return non-NULL");
+ BOOST_ASSERT_MSG( props, "new_properties() must return non-NULL");
// new_properties() must return instance of (a subclass of) PROPS
BOOST_ASSERT_MSG( dynamic_cast< PROPS * >( props),
"new_properties() must return properties class");
- super::set_properties( f, props);
+ super::set_properties( ctx, props);
}
// Set algo_ again every time this fiber becomes READY. That
// handles the case of a fiber migrating to a new thread with a new
@@ -77,31 +77,31 @@ struct algorithm_with_properties : public algorithm_with_properties_base {
props->set_algorithm( this);
// Okay, now forward the call to subclass override.
- awakened( f, properties(f) );
+ awakened( ctx, properties( ctx) );
}
// subclasses override this method instead of the original awakened()
- virtual void awakened( context *, PROPS& ) noexcept = 0;
+ virtual void awakened( context *, PROPS &) noexcept = 0;
// used for all internal calls
- PROPS & properties( context * f) noexcept {
- return static_cast< PROPS & >( * super::get_properties( f) );
+ PROPS & properties( context * ctx) noexcept {
+ return static_cast< PROPS & >( * super::get_properties( ctx) );
}
// override this to be notified by PROPS::notify()
- virtual void property_change( context * f, PROPS & props) noexcept {
+ virtual void property_change( context * ctx, PROPS & props) noexcept {
}
// implementation for algorithm_with_properties_base method
- void property_change_( context * f, fiber_properties * props ) noexcept override final {
- property_change( f, * static_cast< PROPS * >( props) );
+ void property_change_( context * ctx, fiber_properties * props) noexcept override final {
+ property_change( ctx, * static_cast< PROPS * >( props) );
}
// Override this to customize instantiation of PROPS, e.g. use a different
// allocator. Each PROPS instance is associated with a particular
// context.
- virtual fiber_properties * new_properties( context * f) {
- return new PROPS( f);
+ virtual fiber_properties * new_properties( context * ctx) {
+ return new PROPS( ctx);
}
};
diff --git a/boost/fiber/algo/detail/chase_lev_queue.hpp b/boost/fiber/algo/detail/chase_lev_queue.hpp
deleted file mode 100644
index f51556020d..0000000000
--- a/boost/fiber/algo/detail/chase_lev_queue.hpp
+++ /dev/null
@@ -1,172 +0,0 @@
-
-// Copyright Oliver Kowalke 2013.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_FIBERS_ALGO_DETAIL_CHASE_LEV_QUEUE_H
-#define BOOST_FIBERS_ALGO_DETAIL_CHASE_LEV_QUEUE_H
-
-#include <atomic>
-#include <cstddef>
-#include <memory>
-#include <type_traits>
-#include <vector>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-
-#include <boost/fiber/detail/config.hpp>
-#include <boost/fiber/context.hpp>
-
-// David Chase and Yossi Lev. Dynamic circular work-stealing deque.
-// In SPAA ’05: Proceedings of the seventeenth annual ACM symposium
-// on Parallelism in algorithms and architectures, pages 21–28,
-// New York, NY, USA, 2005. ACM.
-//
-// Nhat Minh Lê, Antoniu Pop, Albert Cohen, and Francesco Zappa Nardelli. 2013.
-// Correct and efficient work-stealing for weak memory models.
-// In Proceedings of the 18th ACM SIGPLAN symposium on Principles and practice
-// of parallel programming (PPoPP '13). ACM, New York, NY, USA, 69-80.
-namespace boost {
-namespace fibers {
-namespace algo {
-namespace detail {
-
-class chase_lev_queue {
-private:
- class circular_buffer {
- private:
- typedef typename std::aligned_storage< sizeof( context *), alignof( context *) >::type storage_t;
-
- int64_t size_;
- context ** items;
- chase_lev_queue * queue_;
-
- public:
- circular_buffer( int64_t size, chase_lev_queue * queue) noexcept :
- size_{ size },
- items{ reinterpret_cast< context ** >( new storage_t[size_] ) },
- queue_{ queue } {
- }
-
- ~circular_buffer() {
- delete [] reinterpret_cast< storage_t * >( items);
- }
-
- int64_t size() const noexcept {
- return size_;
- }
-
- context * get( int64_t idx) noexcept {
- BOOST_ASSERT( 0 <= idx);
- return * (items + (idx & (size() - 1)));
- }
-
- void put( int64_t idx, context * ctx) noexcept {
- BOOST_ASSERT( 0 <= idx);
- * (items + (idx & (size() - 1))) = ctx;
- }
-
- circular_buffer * grow( int64_t top, int64_t bottom) {
- BOOST_ASSERT( 0 <= top);
- BOOST_ASSERT( 0 <= bottom);
- circular_buffer * buffer = new circular_buffer{ size() * 2, queue_ };
- queue_->old_buffers_.push_back( this);
- for ( int64_t i = top; i != bottom; ++i) {
- buffer->put( i, get( i) );
- }
- return buffer;
- }
- };
-
- std::atomic< int64_t > top_{ 0 };
- std::atomic< int64_t > bottom_{ 0 };
- std::atomic< circular_buffer * > buffer_;
- std::vector< circular_buffer * > old_buffers_;
-
-public:
- chase_lev_queue() :
- buffer_{ new circular_buffer{ 1024, this } } {
- old_buffers_.resize( 10);
- }
-
- ~chase_lev_queue() {
- delete buffer_.load( std::memory_order_seq_cst);
- for ( circular_buffer * buffer : old_buffers_) {
- delete buffer;
- }
- }
-
- chase_lev_queue( chase_lev_queue const&) = delete;
- chase_lev_queue( chase_lev_queue &&) = delete;
-
- chase_lev_queue & operator=( chase_lev_queue const&) = delete;
- chase_lev_queue & operator=( chase_lev_queue &&) = delete;
-
- bool empty() const noexcept {
- int64_t bottom = bottom_.load( std::memory_order_relaxed);
- int64_t top = top_.load( std::memory_order_relaxed);
- return bottom <= top;
- }
-
- void push( context * ctx) {
- int64_t bottom = bottom_.load( std::memory_order_relaxed);
- int64_t top = top_.load( std::memory_order_acquire);
- circular_buffer * buffer = buffer_.load( std::memory_order_relaxed);
- if ( (bottom - top) > buffer->size() - 1) {
- // queue is full
- buffer = buffer->grow( top, bottom);
- buffer_.store( buffer, std::memory_order_release);
- }
- buffer->put( bottom, ctx);
- std::atomic_thread_fence( std::memory_order_release);
- bottom_.store( bottom + 1, std::memory_order_relaxed);
- }
-
- context * pop() {
- int64_t bottom = bottom_.load( std::memory_order_relaxed) - 1;
- circular_buffer * buffer = buffer_.load( std::memory_order_relaxed);
- bottom_.store( bottom, std::memory_order_relaxed);
- std::atomic_thread_fence( std::memory_order_seq_cst);
- int64_t top = top_.load( std::memory_order_relaxed);
- context * ctx = nullptr;
- if ( top <= bottom) {
- // queue is not empty
- ctx = buffer->get( bottom);
- // last element
- if ( top == bottom) {
- if ( ! top_.compare_exchange_strong( top, top + 1,
- std::memory_order_seq_cst, std::memory_order_relaxed) ) {
- return nullptr;
- }
- bottom_.store( bottom + 1, std::memory_order_relaxed);
- }
- } else {
- // queue is empty
- bottom_.store( bottom + 1, std::memory_order_relaxed);
- }
- return ctx;
- }
-
- context * steal() {
- int64_t top = top_.load( std::memory_order_acquire);
- std::atomic_thread_fence( std::memory_order_seq_cst);
- int64_t bottom = bottom_.load( std::memory_order_acquire);
- context * ctx = nullptr;
- if ( top < bottom) {
- // queue is not empty
- circular_buffer * buffer = buffer_.load( std::memory_order_consume);
- ctx = buffer->get( top);
- if ( ! top_.compare_exchange_strong( top, top + 1,
- std::memory_order_seq_cst, std::memory_order_relaxed) ) {
- return nullptr;
- }
- }
- return ctx;
- }
-};
-
-}}}}
-
-#endif // #define BOOST_FIBERS_ALGO_DETAIL_CHASE_LEV_QUEUE_H
diff --git a/boost/fiber/algo/round_robin.hpp b/boost/fiber/algo/round_robin.hpp
index 038b424529..e384982567 100644
--- a/boost/fiber/algo/round_robin.hpp
+++ b/boost/fiber/algo/round_robin.hpp
@@ -32,9 +32,9 @@ namespace algo {
class BOOST_FIBERS_DECL round_robin : public algorithm {
private:
- typedef scheduler::ready_queue_t rqueue_t;
+ typedef scheduler::ready_queue_type rqueue_type;
- rqueue_t rqueue_{};
+ rqueue_type rqueue_{};
std::mutex mtx_{};
std::condition_variable cnd_{};
bool flag_{ false };
diff --git a/boost/fiber/algo/shared_work.hpp b/boost/fiber/algo/shared_work.hpp
index e648c5b19f..23bc926e55 100644
--- a/boost/fiber/algo/shared_work.hpp
+++ b/boost/fiber/algo/shared_work.hpp
@@ -34,17 +34,17 @@ namespace algo {
class BOOST_FIBERS_DECL shared_work : public algorithm {
private:
- typedef std::deque< context * > rqueue_t;
- typedef scheduler::ready_queue_t lqueue_t;
+ typedef std::deque< context * > rqueue_type;
+ typedef scheduler::ready_queue_type lqueue_type;
- static rqueue_t rqueue_;
+ static rqueue_type rqueue_;
static std::mutex rqueue_mtx_;
- lqueue_t lqueue_{};
+ lqueue_type lqueue_{};
std::mutex mtx_{};
std::condition_variable cnd_{};
bool flag_{ false };
- bool suspend_;
+ bool suspend_{ false };
public:
shared_work() = default;
@@ -64,7 +64,7 @@ public:
context * pick_next() noexcept;
bool has_ready_fibers() const noexcept {
- std::unique_lock< std::mutex > lock( rqueue_mtx_);
+ std::unique_lock< std::mutex > lock{ rqueue_mtx_ };
return ! rqueue_.empty() || ! lqueue_.empty();
}
diff --git a/boost/fiber/algo/work_stealing.hpp b/boost/fiber/algo/work_stealing.hpp
index 12364ece8c..66cadd12be 100644
--- a/boost/fiber/algo/work_stealing.hpp
+++ b/boost/fiber/algo/work_stealing.hpp
@@ -17,6 +17,7 @@
#include <boost/config.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>
@@ -32,45 +33,46 @@ namespace algo {
class work_stealing : public algorithm {
private:
- typedef scheduler::ready_queue_t lqueue_t;
-
- static std::vector< work_stealing * > schedulers_;
-
- std::size_t idx_;
- std::size_t max_idx_;
- detail::context_spmc_queue rqueue_{};
- lqueue_t lqueue_{};
- std::mutex mtx_{};
- std::condition_variable cnd_{};
- bool flag_{ false };
- bool suspend_;
+ static std::vector< work_stealing * > schedulers_;
+
+ std::size_t idx_;
+ std::size_t max_idx_;
+#ifdef BOOST_FIBERS_USE_SPMC_QUEUE
+ alignas(cache_alignment) detail::context_spmc_queue rqueue_{};
+#else
+ alignas(cache_alignment) 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);
public:
work_stealing( std::size_t max_idx, std::size_t idx, bool suspend = false);
- work_stealing( work_stealing const&) = delete;
- work_stealing( work_stealing &&) = delete;
+ work_stealing( work_stealing const&) = delete;
+ work_stealing( work_stealing &&) = delete;
- work_stealing & operator=( work_stealing const&) = delete;
- work_stealing & operator=( work_stealing &&) = delete;
+ work_stealing & operator=( work_stealing const&) = delete;
+ work_stealing & operator=( work_stealing &&) = delete;
void awakened( context * ctx) noexcept;
context * pick_next() noexcept;
context * steal() noexcept {
- return rqueue_.pop();
+ return rqueue_.steal();
}
bool has_ready_fibers() const noexcept {
- return ! rqueue_.empty() || ! lqueue_.empty();
+ return ! rqueue_.empty();
}
- void suspend_until( std::chrono::steady_clock::time_point const& time_point) noexcept;
+ void suspend_until( std::chrono::steady_clock::time_point const& time_point) noexcept;
- void notify() noexcept;
+ void notify() noexcept;
};
}}}
diff --git a/boost/fiber/barrier.hpp b/boost/fiber/barrier.hpp
index debe7d725a..31a2cd617d 100644
--- a/boost/fiber/barrier.hpp
+++ b/boost/fiber/barrier.hpp
@@ -24,19 +24,19 @@ namespace fibers {
class BOOST_FIBERS_DECL barrier {
private:
- std::size_t initial_;
- std::size_t current_;
- bool cycle_{ true };
- mutex mtx_{};
- condition_variable cond_{};
+ std::size_t initial_;
+ std::size_t current_;
+ std::size_t cycle_{ 0 };
+ mutex mtx_{};
+ condition_variable cond_{};
public:
- explicit barrier( std::size_t);
+ explicit barrier( std::size_t);
barrier( barrier const&) = delete;
barrier & operator=( barrier const&) = delete;
- bool wait();
+ bool wait();
};
}}
diff --git a/boost/fiber/bounded_channel.hpp b/boost/fiber/bounded_channel.hpp
deleted file mode 100644
index ac257b4ff5..0000000000
--- a/boost/fiber/bounded_channel.hpp
+++ /dev/null
@@ -1,433 +0,0 @@
-
-// Copyright Oliver Kowalke 2013.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_FIBERS_BOUNDED_CHANNEL_H
-#define BOOST_FIBERS_BOUNDED_CHANNEL_H
-
-#warn "template bounded_channel is deprecated"
-
-#include <algorithm>
-#include <atomic>
-#include <chrono>
-#include <cstddef>
-#include <memory>
-#include <mutex>
-#include <system_error>
-#include <utility>
-
-#include <boost/config.hpp>
-#include <boost/intrusive_ptr.hpp>
-
-#include <boost/fiber/detail/config.hpp>
-#include <boost/fiber/exceptions.hpp>
-#include <boost/fiber/exceptions.hpp>
-#include <boost/fiber/condition_variable.hpp>
-#include <boost/fiber/mutex.hpp>
-#include <boost/fiber/channel_op_status.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace fibers {
-
-template< typename T,
- typename Allocator = std::allocator< T >
->
-class bounded_channel {
-public:
- typedef T value_type;
-
-private:
- struct node {
- typedef intrusive_ptr< node > ptr_t;
- typedef typename std::allocator_traits< Allocator >::template rebind_alloc<
- node
- > allocator_t;
- typedef std::allocator_traits< allocator_t > allocator_traits_t;
-
-#if ! defined(BOOST_FIBERS_NO_ATOMICS)
- std::atomic< std::size_t > use_count{ 0 };
-#else
- std::size_t use_count{ 0 };
-#endif
- allocator_t alloc;
- T va;
- ptr_t nxt{};
-
- node( T const& t, allocator_t const& alloc_) noexcept :
- alloc{ alloc_ },
- va{ t } {
- }
-
- node( T && t, allocator_t & alloc_) noexcept :
- alloc{ alloc_ },
- va{ std::move( t) } {
- }
-
- friend
- void intrusive_ptr_add_ref( node * p) noexcept {
- ++p->use_count;
- }
-
- friend
- void intrusive_ptr_release( node * p) noexcept {
- if ( 0 == --p->use_count) {
- allocator_t alloc( p->alloc);
- allocator_traits_t::destroy( alloc, p);
- allocator_traits_t::deallocate( alloc, p, 1);
- }
- }
- };
-
- using ptr_t = typename node::ptr_t;
- using allocator_t = typename node::allocator_t;
- using allocator_traits_t = typename node::allocator_traits_t;
-
- enum class queue_status {
- open = 0,
- closed
- };
-
- allocator_t alloc_;
- queue_status state_{ queue_status::open };
- std::size_t count_{ 0 };
- ptr_t head_{};
- ptr_t * tail_;
- mutable mutex mtx_{};
- condition_variable not_empty_cond_{};
- condition_variable not_full_cond_{};
- std::size_t hwm_;
- std::size_t lwm_;
-
- bool is_closed_() const noexcept {
- return queue_status::closed == state_;
- }
-
- void close_( std::unique_lock< boost::fibers::mutex > & lk) noexcept {
- state_ = queue_status::closed;
- lk.unlock();
- not_empty_cond_.notify_all();
- not_full_cond_.notify_all();
- }
-
- std::size_t size_() const noexcept {
- return count_;
- }
-
- bool is_empty_() const noexcept {
- return ! head_;
- }
-
- bool is_full_() const noexcept {
- return count_ >= hwm_;
- }
-
- channel_op_status push_( ptr_t new_node,
- std::unique_lock< boost::fibers::mutex > & lk) {
- if ( is_closed_() ) {
- return channel_op_status::closed;
- }
- not_full_cond_.wait( lk,
- [this](){
- return ! is_full_();
- });
- return push_and_notify_( new_node, lk);
- }
-
- channel_op_status try_push_( ptr_t new_node,
- std::unique_lock< boost::fibers::mutex > & lk) noexcept {
- if ( is_closed_() ) {
- return channel_op_status::closed;
- }
- if ( is_full_() ) {
- return channel_op_status::full;
- }
- return push_and_notify_( new_node, lk);
- }
-
- template< typename Clock, typename Duration >
- channel_op_status push_wait_until_( ptr_t new_node,
- std::chrono::time_point< Clock, Duration > const& timeout_time,
- std::unique_lock< boost::fibers::mutex > & lk) {
- if ( is_closed_() ) {
- return channel_op_status::closed;
- }
- if ( ! not_full_cond_.wait_until( lk, timeout_time,
- [this](){
- return ! is_full_();
- })) {
- return channel_op_status::timeout;
- }
- return push_and_notify_( new_node, lk);
- }
-
- channel_op_status push_and_notify_( ptr_t new_node,
- std::unique_lock< boost::fibers::mutex > & lk) noexcept {
- push_tail_( new_node);
- lk.unlock();
- not_empty_cond_.notify_one();
- return channel_op_status::success;
- }
-
- void push_tail_( ptr_t new_node) noexcept {
- * tail_ = new_node;
- tail_ = & new_node->nxt;
- ++count_;
- }
-
- value_type value_pop_( std::unique_lock< boost::fibers::mutex > & lk) {
- BOOST_ASSERT( ! is_empty_() );
- auto old_head = pop_head_();
- if ( size_() <= lwm_) {
- if ( lwm_ == hwm_) {
- lk.unlock();
- not_full_cond_.notify_one();
- } else {
- lk.unlock();
- // more than one producer could be waiting
- // to push a value
- not_full_cond_.notify_all();
- }
- }
- return std::move( old_head->va);
- }
-
- ptr_t pop_head_() noexcept {
- auto old_head = head_;
- head_ = old_head->nxt;
- if ( ! head_) {
- tail_ = & head_;
- }
- old_head->nxt.reset();
- --count_;
- return old_head;
- }
-
-public:
- bounded_channel( std::size_t hwm, std::size_t lwm,
- Allocator const& alloc = Allocator() ) :
- alloc_{ alloc },
- tail_{ & head_ },
- hwm_{ hwm },
- lwm_{ lwm } {
- if ( hwm_ <= lwm_) {
- throw fiber_error( std::make_error_code( std::errc::invalid_argument),
- "boost fiber: high-watermark is less than or equal to low-watermark for bounded_channel");
- }
- if ( 0 == hwm) {
- throw fiber_error( std::make_error_code( std::errc::invalid_argument),
- "boost fiber: high-watermark is zero");
- }
- }
-
- bounded_channel( std::size_t wm,
- Allocator const& alloc = Allocator() ) :
- alloc_{ alloc },
- tail_{ & head_ },
- hwm_{ wm },
- lwm_{ wm - 1 } {
- if ( 0 == wm) {
- throw fiber_error( std::make_error_code( std::errc::invalid_argument),
- "boost fiber: watermark is zero");
- }
- }
-
- bounded_channel( bounded_channel const&) = delete;
- bounded_channel & operator=( bounded_channel const&) = delete;
-
- std::size_t upper_bound() const noexcept {
- return hwm_;
- }
-
- std::size_t lower_bound() const noexcept {
- return lwm_;
- }
-
- void close() noexcept {
- std::unique_lock< mutex > lk( mtx_);
- close_( lk);
- }
-
- channel_op_status push( value_type const& va) {
- typename allocator_traits_t::pointer ptr{
- allocator_traits_t::allocate( alloc_, 1) };
- try {
- allocator_traits_t::construct( alloc_, ptr, va, alloc_);
- } catch (...) {
- allocator_traits_t::deallocate( alloc_, ptr, 1);
- throw;
- }
- std::unique_lock< mutex > lk( mtx_);
- return push_( { detail::convert( ptr) }, lk);
- }
-
- channel_op_status push( value_type && va) {
- typename allocator_traits_t::pointer ptr{
- allocator_traits_t::allocate( alloc_, 1) };
- try {
- allocator_traits_t::construct(
- alloc_, ptr, std::move( va), alloc_);
- } catch (...) {
- allocator_traits_t::deallocate( alloc_, ptr, 1);
- throw;
- }
- std::unique_lock< mutex > lk( mtx_);
- return push_( { detail::convert( ptr) }, lk);
- }
-
- template< typename Rep, typename Period >
- channel_op_status push_wait_for( value_type const& va,
- std::chrono::duration< Rep, Period > const& timeout_duration) {
- return push_wait_until( va,
- std::chrono::steady_clock::now() + timeout_duration);
- }
-
- template< typename Rep, typename Period >
- channel_op_status push_wait_for( value_type && va,
- std::chrono::duration< Rep, Period > const& timeout_duration) {
- return push_wait_until( std::forward< value_type >( va),
- std::chrono::steady_clock::now() + timeout_duration);
- }
-
- template< typename Clock, typename Duration >
- channel_op_status push_wait_until( value_type const& va,
- std::chrono::time_point< Clock, Duration > const& timeout_time) {
- typename allocator_traits_t::pointer ptr{
- allocator_traits_t::allocate( alloc_, 1) };
- try {
- allocator_traits_t::construct( alloc_, ptr, va, alloc_);
- } catch (...) {
- allocator_traits_t::deallocate( alloc_, ptr, 1);
- throw;
- }
- std::unique_lock< mutex > lk( mtx_);
- return push_wait_until_( { detail::convert( ptr) }, timeout_time, lk);
- }
-
- template< typename Clock, typename Duration >
- channel_op_status push_wait_until( value_type && va,
- std::chrono::time_point< Clock, Duration > const& timeout_time) {
- typename allocator_traits_t::pointer ptr{
- allocator_traits_t::allocate( alloc_, 1) };
- try {
- allocator_traits_t::construct(
- alloc_, ptr, std::move( va), alloc_);
- } catch (...) {
- allocator_traits_t::deallocate( alloc_, ptr, 1);
- throw;
- }
- std::unique_lock< mutex > lk( mtx_);
- return push_wait_until_( { detail::convert( ptr) }, timeout_time, lk);
- }
-
- channel_op_status try_push( value_type const& va) {
- typename allocator_traits_t::pointer ptr{
- allocator_traits_t::allocate( alloc_, 1) };
- try {
- allocator_traits_t::construct( alloc_, ptr, va, alloc_);
- } catch (...) {
- allocator_traits_t::deallocate( alloc_, ptr, 1);
- throw;
- }
- std::unique_lock< mutex > lk( mtx_);
- return try_push_( { detail::convert( ptr) }, lk);
- }
-
- channel_op_status try_push( value_type && va) {
- typename allocator_traits_t::pointer ptr{
- allocator_traits_t::allocate( alloc_, 1) };
- try {
- allocator_traits_t::construct(
- alloc_, ptr, std::move( va), alloc_);
- } catch (...) {
- allocator_traits_t::deallocate( alloc_, ptr, 1);
- throw;
- }
- std::unique_lock< mutex > lk( mtx_);
- return try_push_( { detail::convert( ptr) }, lk);
- }
-
- channel_op_status pop( value_type & va) {
- std::unique_lock< mutex > lk( mtx_);
- not_empty_cond_.wait( lk,
- [this](){
- return is_closed_() || ! is_empty_();
- });
- if ( is_closed_() && is_empty_() ) {
- return channel_op_status::closed;
- }
- va = value_pop_( lk);
- return channel_op_status::success;
- }
-
- value_type value_pop() {
- std::unique_lock< mutex > lk( mtx_);
- not_empty_cond_.wait( lk,
- [this](){
- return is_closed_() || ! is_empty_();
- });
- if ( is_closed_() && is_empty_() ) {
- throw fiber_error(
- std::make_error_code( std::errc::operation_not_permitted),
- "boost fiber: queue is closed");
- }
- return value_pop_( lk);
- }
-
- channel_op_status try_pop( value_type & va) {
- std::unique_lock< mutex > lk( mtx_);
- if ( is_closed_() && is_empty_() ) {
- // let other fibers run
- lk.unlock();
- this_fiber::yield();
- return channel_op_status::closed;
- }
- if ( is_empty_() ) {
- // let other fibers run
- lk.unlock();
- this_fiber::yield();
- return channel_op_status::empty;
- }
- va = value_pop_( lk);
- return channel_op_status::success;
- }
-
- template< typename Rep, typename Period >
- channel_op_status pop_wait_for( value_type & va,
- std::chrono::duration< Rep, Period > const& timeout_duration) {
- return pop_wait_until( va,
- std::chrono::steady_clock::now() + timeout_duration);
- }
-
- template< typename Clock, typename Duration >
- channel_op_status pop_wait_until( value_type & va,
- std::chrono::time_point< Clock, Duration > const& timeout_time) {
- std::unique_lock< mutex > lk( mtx_);
- if ( ! not_empty_cond_.wait_until( lk,
- timeout_time,
- [this](){
- return is_closed_() || ! is_empty_();
- })) {
- return channel_op_status::timeout;
- }
- if ( is_closed_() && is_empty_() ) {
- return channel_op_status::closed;
- }
- va = value_pop_( lk);
- return channel_op_status::success;
- }
-};
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_FIBERS_BOUNDED_CHANNEL_H
diff --git a/boost/fiber/buffered_channel.hpp b/boost/fiber/buffered_channel.hpp
index 25109a4976..1c32e49bae 100644
--- a/boost/fiber/buffered_channel.hpp
+++ b/boost/fiber/buffered_channel.hpp
@@ -4,8 +4,6 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
-// based on Dmitry Vyukov's MPMC queue
-// (http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue)
#ifndef BOOST_FIBERS_BUFFERED_CHANNEL_H
#define BOOST_FIBERS_BUFFERED_CHANNEL_H
@@ -39,120 +37,42 @@ public:
typedef T value_type;
private:
- typedef typename std::aligned_storage< sizeof( T), alignof( T) >::type storage_type;
- typedef context::wait_queue_t wait_queue_type;
-
- struct alignas(cache_alignment) slot {
- std::atomic< std::size_t > cycle{ 0 };
- storage_type storage{};
-
- slot() = default;
- };
-
- // procuder cacheline
- alignas(cache_alignment) std::atomic< std::size_t > producer_idx_{ 0 };
- // consumer cacheline
- alignas(cache_alignment) std::atomic< std::size_t > consumer_idx_{ 0 };
- // shared write cacheline
- alignas(cache_alignment) std::atomic_bool closed_{ false };
- mutable detail::spinlock splk_{};
- wait_queue_type waiting_producers_{};
- wait_queue_type waiting_consumers_{};
- // shared read cacheline
- alignas(cache_alignment) slot * slots_{ nullptr };
- std::size_t capacity_;
- char pad_[cacheline_length];
-
- bool is_full_() {
- std::size_t idx{ producer_idx_.load( std::memory_order_relaxed) };
- return 0 > static_cast< std::intptr_t >( slots_[idx & (capacity_ - 1)].cycle.load( std::memory_order_acquire) ) - static_cast< std::intptr_t >( idx);
- }
-
- bool is_empty_() {
- std::size_t idx{ consumer_idx_.load( std::memory_order_relaxed) };
- return 0 > static_cast< std::intptr_t >( slots_[idx & (capacity_ - 1)].cycle.load( std::memory_order_acquire) ) - static_cast< std::intptr_t >( idx + 1);
- }
-
- template< typename ValueType >
- channel_op_status try_push_( ValueType && value) {
- slot * s{ nullptr };
- std::size_t idx{ producer_idx_.load( std::memory_order_relaxed) };
- for (;;) {
- s = & slots_[idx & (capacity_ - 1)];
- std::size_t cycle{ s->cycle.load( std::memory_order_acquire) };
- std::intptr_t diff{ static_cast< std::intptr_t >( cycle) - static_cast< std::intptr_t >( idx) };
- if ( 0 == diff) {
- if ( producer_idx_.compare_exchange_weak( idx, idx + 1, std::memory_order_relaxed) ) {
- break;
- }
- } else if ( 0 > diff) {
- return channel_op_status::full;
- } else {
- idx = producer_idx_.load( std::memory_order_relaxed);
- }
- }
- ::new ( static_cast< void * >( std::addressof( s->storage) ) ) value_type( std::forward< ValueType >( value) );
- s->cycle.store( idx + 1, std::memory_order_release);
- return channel_op_status::success;
- }
-
- channel_op_status try_value_pop_( slot *& s, std::size_t & idx) {
- idx = consumer_idx_.load( std::memory_order_relaxed);
- for (;;) {
- s = & slots_[idx & (capacity_ - 1)];
- std::size_t cycle = s->cycle.load( std::memory_order_acquire);
- std::intptr_t diff{ static_cast< std::intptr_t >( cycle) - static_cast< std::intptr_t >( idx + 1) };
- if ( 0 == diff) {
- if ( consumer_idx_.compare_exchange_weak( idx, idx + 1, std::memory_order_relaxed) ) {
- break;
- }
- } else if ( 0 > diff) {
- return channel_op_status::empty;
- } else {
- idx = consumer_idx_.load( std::memory_order_relaxed);
- }
- }
- // incrementing the slot cycle must be deferred till the value has been consumed
- // slot cycle tells procuders that the cell can be re-used (store new value)
- return channel_op_status::success;
- }
-
- channel_op_status try_pop_( value_type & value) {
- slot * s{ nullptr };
- std::size_t idx{ 0 };
- channel_op_status status{ try_value_pop_( s, idx) };
- if ( channel_op_status::success == status) {
- value = std::move( * reinterpret_cast< value_type * >( std::addressof( s->storage) ) );
- s->cycle.store( idx + capacity_, std::memory_order_release);
- }
- return status;
+ typedef context::wait_queue_t wait_queue_type;
+ typedef T slot_type;
+
+ alignas(cache_alignment) mutable detail::spinlock splk_{};
+ wait_queue_type waiting_producers_{};
+ wait_queue_type waiting_consumers_{};
+ slot_type * slots_;
+ std::size_t pidx_{ 0 };
+ std::size_t cidx_{ 0 };
+ std::size_t capacity_;
+ bool closed_{ false };
+
+ bool is_full_() const noexcept {
+ return cidx_ == ((pidx_ + 1) % capacity_);
+ }
+
+ bool is_empty_() const noexcept {
+ return cidx_ == pidx_;
+ }
+
+ bool is_closed_() const noexcept {
+ return closed_;
}
public:
explicit buffered_channel( std::size_t capacity) :
- capacity_{ capacity } {
- if ( 0 == capacity_ || 0 != ( capacity_ & (capacity_ - 1) ) ) {
- throw fiber_error( std::make_error_code( std::errc::invalid_argument),
- "boost fiber: buffer capacity is invalid");
- }
- slots_ = new slot[capacity_]();
- for ( std::size_t i = 0; i < capacity_; ++i) {
- slots_[i].cycle.store( i, std::memory_order_relaxed);
+ capacity_{ capacity } {
+ if ( 2 > capacity_ || 0 != ( capacity_ & (capacity_ - 1) ) ) {
+ throw fiber_error{ std::make_error_code( std::errc::invalid_argument),
+ "boost fiber: buffer capacity is invalid" };
}
+ slots_ = new slot_type[capacity_];
}
~buffered_channel() {
close();
- for (;;) {
- slot * s{ nullptr };
- std::size_t idx{ 0 };
- if ( channel_op_status::success == try_value_pop_( s, idx) ) {
- reinterpret_cast< value_type * >( std::addressof( s->storage) )->~value_type();
- s->cycle.store( idx + capacity_, std::memory_order_release);
- } else {
- break;
- }
- }
delete [] slots_;
}
@@ -160,109 +80,116 @@ public:
buffered_channel & operator=( buffered_channel const&) = delete;
bool is_closed() const noexcept {
- return closed_.load( std::memory_order_acquire);
+ detail::spinlock_lock lk{ splk_ };
+ return is_closed_();
}
void close() noexcept {
- context * ctx{ context::active() };
+ context * active_ctx = context::active();
detail::spinlock_lock lk{ splk_ };
- closed_.store( true, std::memory_order_release);
+ closed_ = true;
// notify all waiting producers
while ( ! waiting_producers_.empty() ) {
- context * producer_ctx{ & waiting_producers_.front() };
+ context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
- ctx->set_ready( producer_ctx);
+ active_ctx->schedule( producer_ctx);
}
// notify all waiting consumers
while ( ! waiting_consumers_.empty() ) {
- context * consumer_ctx{ & waiting_consumers_.front() };
+ context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- ctx->set_ready( consumer_ctx);
+ active_ctx->schedule( consumer_ctx);
}
}
channel_op_status try_push( value_type const& value) {
- if ( is_closed() ) {
+ context * active_ctx = context::active();
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed_() ) {
return channel_op_status::closed;
+ } else if ( is_full_() ) {
+ return channel_op_status::full;
+ } else {
+ slots_[pidx_] = value;
+ pidx_ = (pidx_ + 1) % capacity_;
+ // notify one waiting consumer
+ if ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx = & waiting_consumers_.front();
+ waiting_consumers_.pop_front();
+ lk.unlock();
+ active_ctx->schedule( consumer_ctx);
+ }
+ return channel_op_status::success;
}
- return try_push_( value);
}
channel_op_status try_push( value_type && value) {
- if ( is_closed() ) {
+ context * active_ctx = context::active();
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed_() ) {
return channel_op_status::closed;
+ } else if ( is_full_() ) {
+ return channel_op_status::full;
+ } else {
+ slots_[pidx_] = std::move( value);
+ pidx_ = (pidx_ + 1) % capacity_;
+ // notify one waiting consumer
+ if ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx = & waiting_consumers_.front();
+ waiting_consumers_.pop_front();
+ lk.unlock();
+ active_ctx->schedule( consumer_ctx);
+ }
+ return channel_op_status::success;
}
- return try_push_( std::move( value) );
}
channel_op_status push( value_type const& value) {
- context * ctx{ context::active() };
+ context * active_ctx = context::active();
for (;;) {
- if ( is_closed() ) {
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed_() ) {
return channel_op_status::closed;
- }
- channel_op_status status{ try_push_( value) };
- if ( channel_op_status::success == status) {
- detail::spinlock_lock lk{ splk_ };
+ } else if ( is_full_() ) {
+ active_ctx->wait_link( waiting_producers_);
+ // suspend this producer
+ active_ctx->suspend( lk);
+ } else {
+ slots_[pidx_] = value;
+ pidx_ = (pidx_ + 1) % capacity_;
// notify one waiting consumer
if ( ! waiting_consumers_.empty() ) {
- context * consumer_ctx{ & waiting_consumers_.front() };
+ context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
lk.unlock();
- ctx->set_ready( consumer_ctx);
- }
- return status;
- } else if ( channel_op_status::full == status) {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
- if ( is_closed() ) {
- return channel_op_status::closed;
+ active_ctx->schedule( consumer_ctx);
}
- if ( ! is_full_() ) {
- continue;
- }
- ctx->wait_link( waiting_producers_);
- // suspend this producer
- ctx->suspend( lk);
- } else {
- BOOST_ASSERT( channel_op_status::closed == status);
- return status;
+ return channel_op_status::success;
}
}
}
channel_op_status push( value_type && value) {
- context * ctx{ context::active() };
+ context * active_ctx = context::active();
for (;;) {
- if ( is_closed() ) {
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed_() ) {
return channel_op_status::closed;
- }
- channel_op_status status{ try_push_( std::move( value) ) };
- if ( channel_op_status::success == status) {
- detail::spinlock_lock lk{ splk_ };
+ } else if ( is_full_() ) {
+ active_ctx->wait_link( waiting_producers_);
+ // 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() ) {
- context * consumer_ctx{ & waiting_consumers_.front() };
+ context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
lk.unlock();
- ctx->set_ready( consumer_ctx);
+ active_ctx->schedule( consumer_ctx);
}
- return status;
- } else if ( channel_op_status::full == status) {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
- if ( is_closed() ) {
- return channel_op_status::closed;
- }
- if ( ! is_full_() ) {
- continue;
- }
- ctx->wait_link( waiting_producers_);
- // suspend this producer
- ctx->suspend( lk);
- } else {
- BOOST_ASSERT( channel_op_status::closed == status);
- return status;
+ return channel_op_status::success;
}
}
}
@@ -284,44 +211,33 @@ public:
template< typename Clock, typename Duration >
channel_op_status push_wait_until( value_type const& value,
std::chrono::time_point< Clock, Duration > const& timeout_time_) {
- std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) );
- context * ctx{ context::active() };
+ context * active_ctx = context::active();
+ std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
for (;;) {
- if ( is_closed() ) {
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed_() ) {
return channel_op_status::closed;
- }
- channel_op_status status{ try_push_( value) };
- if ( channel_op_status::success == status) {
- detail::spinlock_lock lk{ splk_ };
- // notify one waiting consumer
- if ( ! waiting_consumers_.empty() ) {
- context * consumer_ctx{ & waiting_consumers_.front() };
- waiting_consumers_.pop_front();
- lk.unlock();
- ctx->set_ready( consumer_ctx);
- }
- return status;
- } else if ( channel_op_status::full == status) {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
- if ( is_closed() ) {
- return channel_op_status::closed;
- }
- if ( ! is_full_() ) {
- continue;
- }
- ctx->wait_link( waiting_producers_);
+ } else if ( is_full_() ) {
+ active_ctx->wait_link( waiting_producers_);
// suspend this producer
- if ( ! ctx->wait_until( timeout_time, lk) ) {
+ if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// relock local lk
lk.lock();
// remove from waiting-queue
- ctx->wait_unlink();
+ waiting_producers_.remove( * active_ctx);
return channel_op_status::timeout;
}
} else {
- BOOST_ASSERT( channel_op_status::closed == status);
- return status;
+ slots_[pidx_] = value;
+ pidx_ = (pidx_ + 1) % capacity_;
+ // notify one waiting consumer
+ if ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx = & waiting_consumers_.front();
+ waiting_consumers_.pop_front();
+ lk.unlock();
+ active_ctx->schedule( consumer_ctx);
+ }
+ return channel_op_status::success;
}
}
}
@@ -329,128 +245,110 @@ public:
template< typename Clock, typename Duration >
channel_op_status push_wait_until( value_type && value,
std::chrono::time_point< Clock, Duration > const& timeout_time_) {
- std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) );
- context * ctx{ context::active() };
+ context * active_ctx = context::active();
+ std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
for (;;) {
- if ( is_closed() ) {
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_closed_() ) {
return channel_op_status::closed;
- }
- channel_op_status status{ try_push_( std::move( value) ) };
- if ( channel_op_status::success == status) {
- detail::spinlock_lock lk{ splk_ };
- // notify one waiting consumer
- if ( ! waiting_consumers_.empty() ) {
- context * consumer_ctx{ & waiting_consumers_.front() };
- waiting_consumers_.pop_front();
- lk.unlock();
- ctx->set_ready( consumer_ctx);
- }
- return status;
- } else if ( channel_op_status::full == status) {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
- if ( is_closed() ) {
- return channel_op_status::closed;
- }
- if ( ! is_full_() ) {
- continue;
- }
- ctx->wait_link( waiting_producers_);
+ } else if ( is_full_() ) {
+ active_ctx->wait_link( waiting_producers_);
// suspend this producer
- if ( ! ctx->wait_until( timeout_time, lk) ) {
+ if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// relock local lk
lk.lock();
// remove from waiting-queue
- ctx->wait_unlink();
+ waiting_producers_.remove( * active_ctx);
return channel_op_status::timeout;
}
} else {
- BOOST_ASSERT( channel_op_status::closed == status);
- return status;
+ slots_[pidx_] = std::move( value);
+ pidx_ = (pidx_ + 1) % capacity_;
+ // notify one waiting consumer
+ if ( ! waiting_consumers_.empty() ) {
+ context * consumer_ctx = & waiting_consumers_.front();
+ waiting_consumers_.pop_front();
+ lk.unlock();
+ active_ctx->schedule( consumer_ctx);
+ }
+ return channel_op_status::success;
}
}
}
channel_op_status try_pop( value_type & value) {
- channel_op_status status{ try_pop_( value) };
- if ( channel_op_status::success != status) {
- if ( is_closed() ) {
- status = channel_op_status::closed;
+ context * active_ctx = context::active();
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_empty_() ) {
+ return is_closed_()
+ ? channel_op_status::closed
+ : channel_op_status::empty;
+ } else {
+ value = std::move( slots_[cidx_]);
+ cidx_ = (cidx_ + 1) % capacity_;
+ // notify one waiting producer
+ if ( ! waiting_producers_.empty() ) {
+ context * producer_ctx = & waiting_producers_.front();
+ waiting_producers_.pop_front();
+ lk.unlock();
+ active_ctx->schedule( producer_ctx);
}
+ return channel_op_status::success;
}
- return status;
}
channel_op_status pop( value_type & value) {
- context * ctx{ context::active() };
+ context * active_ctx = context::active();
for (;;) {
- channel_op_status status{ try_pop_( value) };
- if ( channel_op_status::success == status) {
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_empty_() ) {
+ if ( is_closed_() ) {
+ return channel_op_status::closed;
+ } else {
+ active_ctx->wait_link( waiting_consumers_);
+ // suspend this consumer
+ active_ctx->suspend( lk);
+ }
+ } else {
+ value = std::move( slots_[cidx_]);
+ cidx_ = (cidx_ + 1) % capacity_;
// notify one waiting producer
if ( ! waiting_producers_.empty() ) {
- context * producer_ctx{ & waiting_producers_.front() };
+ context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- ctx->set_ready( producer_ctx);
+ active_ctx->schedule( producer_ctx);
}
- return status;
- } else if ( channel_op_status::empty == status) {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
- if ( is_closed() ) {
- return channel_op_status::closed;
- }
- if ( ! is_empty_() ) {
- continue;
- }
- ctx->wait_link( waiting_consumers_);
- // suspend this consumer
- ctx->suspend( lk);
- } else {
- BOOST_ASSERT( channel_op_status::closed == status);
- return status;
+ return channel_op_status::success;
}
}
}
value_type value_pop() {
- context * ctx{ context::active() };
+ context * active_ctx = context::active();
for (;;) {
- slot * s{ nullptr };
- std::size_t idx{ 0 };
- channel_op_status status{ try_value_pop_( s, idx) };
- if ( channel_op_status::success == status) {
- value_type value{ std::move( * reinterpret_cast< value_type * >( std::addressof( s->storage) ) ) };
- s->cycle.store( idx + capacity_, std::memory_order_release);
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_empty_() ) {
+ if ( 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_);
+ // suspend this consumer
+ active_ctx->suspend( lk);
+ }
+ } else {
+ value_type value = std::move( slots_[cidx_]);
+ cidx_ = (cidx_ + 1) % capacity_;
// notify one waiting producer
if ( ! waiting_producers_.empty() ) {
- context * producer_ctx{ & waiting_producers_.front() };
+ context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- ctx->set_ready( producer_ctx);
+ active_ctx->schedule( producer_ctx);
}
return std::move( value);
- } else if ( channel_op_status::empty == status) {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
- if ( is_closed() ) {
- throw fiber_error{
- std::make_error_code( std::errc::operation_not_permitted),
- "boost fiber: channel is closed" };
- }
- if ( ! is_empty_() ) {
- continue;
- }
- ctx->wait_link( waiting_consumers_);
- // suspend this consumer
- ctx->suspend( lk);
- } else {
- BOOST_ASSERT( channel_op_status::closed == status);
- throw fiber_error{
- std::make_error_code( std::errc::operation_not_permitted),
- "boost fiber: channel is closed" };
}
}
}
@@ -465,41 +363,35 @@ public:
template< typename Clock, typename Duration >
channel_op_status pop_wait_until( value_type & value,
std::chrono::time_point< Clock, Duration > const& timeout_time_) {
- std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) );
- context * ctx{ context::active() };
+ context * active_ctx = context::active();
+ std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
for (;;) {
- channel_op_status status{ try_pop_( value) };
- if ( channel_op_status::success == status) {
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_ };
+ if ( is_empty_() ) {
+ if ( is_closed_() ) {
+ return channel_op_status::closed;
+ } else {
+ active_ctx->wait_link( waiting_consumers_);
+ // suspend this consumer
+ if ( ! active_ctx->wait_until( timeout_time, lk) ) {
+ // relock local lk
+ lk.lock();
+ // remove from waiting-queue
+ waiting_consumers_.remove( * active_ctx);
+ return channel_op_status::timeout;
+ }
+ }
+ } else {
+ value = std::move( slots_[cidx_]);
+ cidx_ = (cidx_ + 1) % capacity_;
// notify one waiting producer
if ( ! waiting_producers_.empty() ) {
- context * producer_ctx{ & waiting_producers_.front() };
+ context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- context::active()->set_ready( producer_ctx);
- }
- return status;
- } else if ( channel_op_status::empty == status) {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
- if ( is_closed() ) {
- return channel_op_status::closed;
- }
- if ( ! is_empty_() ) {
- continue;
+ active_ctx->schedule( producer_ctx);
}
- ctx->wait_link( waiting_consumers_);
- // suspend this consumer
- if ( ! ctx->wait_until( timeout_time, lk) ) {
- // relock local lk
- lk.lock();
- // remove from waiting-queue
- ctx->wait_unlink();
- return channel_op_status::timeout;
- }
- } else {
- BOOST_ASSERT( channel_op_status::closed == status);
- return status;
+ return channel_op_status::success;
}
}
}
diff --git a/boost/fiber/condition_variable.hpp b/boost/fiber/condition_variable.hpp
index 0dca7ef6a0..cd0e7cb022 100644
--- a/boost/fiber/condition_variable.hpp
+++ b/boost/fiber/condition_variable.hpp
@@ -45,8 +45,8 @@ class BOOST_FIBERS_DECL condition_variable_any {
private:
typedef context::wait_queue_t wait_queue_t;
- wait_queue_t wait_queue_{};
detail::spinlock wait_queue_splk_{};
+ wait_queue_t wait_queue_{};
public:
condition_variable_any() = default;
@@ -64,22 +64,16 @@ public:
template< typename LockType >
void wait( LockType & lt) {
- context * ctx = context::active();
+ context * active_ctx = context::active();
// atomically call lt.unlock() and block on *this
// store this fiber in waiting-queue
- detail::spinlock_lock lk( wait_queue_splk_);
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- ctx->wait_link( wait_queue_);
+ detail::spinlock_lock lk{ wait_queue_splk_ };
+ BOOST_ASSERT( ! active_ctx->wait_is_linked() );
+ active_ctx->wait_link( wait_queue_);
// unlock external lt
lt.unlock();
// suspend this fiber
- ctx->suspend( lk);
- // relock local lk
- lk.lock();
- // remove from waiting-queue
- ctx->wait_unlink();
- // unlock local lk
- lk.unlock();
+ active_ctx->suspend( lk);
// relock external again before returning
try {
lt.lock();
@@ -87,7 +81,7 @@ public:
std::terminate();
}
// post-conditions
- BOOST_ASSERT( ! ctx->wait_is_linked() );
+ BOOST_ASSERT( ! active_ctx->wait_is_linked() );
}
template< typename LockType, typename Pred >
@@ -99,27 +93,26 @@ public:
template< typename LockType, typename Clock, typename Duration >
cv_status wait_until( LockType & lt, std::chrono::time_point< Clock, Duration > const& timeout_time_) {
+ context * active_ctx = context::active();
cv_status status = cv_status::no_timeout;
- std::chrono::steady_clock::time_point timeout_time(
- detail::convert( timeout_time_) );
- context * ctx = context::active();
+ std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
// atomically call lt.unlock() and block on *this
// store this fiber in waiting-queue
- detail::spinlock_lock lk( wait_queue_splk_);
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- ctx->wait_link( wait_queue_);
+ detail::spinlock_lock lk{ wait_queue_splk_ };
+ BOOST_ASSERT( ! active_ctx->wait_is_linked() );
+ active_ctx->wait_link( wait_queue_);
// unlock external lt
lt.unlock();
// suspend this fiber
- if ( ! ctx->wait_until( timeout_time, lk) ) {
+ if ( ! active_ctx->wait_until( timeout_time, lk) ) {
status = cv_status::timeout;
+ // relock local lk
+ lk.lock();
+ // remove from waiting-queue
+ wait_queue_.remove( * active_ctx);
+ // unlock local lk
+ lk.unlock();
}
- // relock local lk
- lk.lock();
- // remove from waiting-queue
- ctx->wait_unlink();
- // unlock local lk
- lk.unlock();
// relock external again before returning
try {
lt.lock();
@@ -127,7 +120,7 @@ public:
std::terminate();
}
// post-conditions
- BOOST_ASSERT( ! ctx->wait_is_linked() );
+ BOOST_ASSERT( ! active_ctx->wait_is_linked() );
return status;
}
diff --git a/boost/fiber/context.hpp b/boost/fiber/context.hpp
index d873343538..773528e3a1 100644
--- a/boost/fiber/context.hpp
+++ b/boost/fiber/context.hpp
@@ -7,23 +7,32 @@
#ifndef BOOST_FIBERS_CONTEXT_H
#define BOOST_FIBERS_CONTEXT_H
+#include <iostream>
#include <atomic>
#include <chrono>
#include <exception>
#include <functional>
#include <map>
#include <memory>
+#include <tuple>
#include <type_traits>
#include <boost/assert.hpp>
#include <boost/config.hpp>
+#if defined(BOOST_NO_CXX17_STD_APPLY)
#include <boost/context/detail/apply.hpp>
-#include <boost/context/execution_context.hpp>
+#endif
+#if (BOOST_EXECUTION_CONTEXT==1)
+# include <boost/context/execution_context.hpp>
+#else
+# include <boost/context/continuation.hpp>
+#endif
#include <boost/context/stack_context.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/parent_from_member.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/intrusive/set.hpp>
+#include <boost/intrusive/slist.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/data.hpp>
@@ -57,10 +66,10 @@ class scheduler;
namespace detail {
struct wait_tag;
-typedef intrusive::list_member_hook<
+typedef intrusive::slist_member_hook<
intrusive::tag< wait_tag >,
intrusive::link_mode<
- intrusive::auto_unlink
+ intrusive::safe_link
>
> wait_hook;
// declaration of the functor that converts between
@@ -97,21 +106,29 @@ typedef intrusive::set_member_hook<
>
> sleep_hook;
-struct terminated_tag;
+struct worker_tag;
typedef intrusive::list_member_hook<
- intrusive::tag< terminated_tag >,
+ intrusive::tag< worker_tag >,
intrusive::link_mode<
intrusive::auto_unlink
>
+> worker_hook;
+
+struct terminated_tag;
+typedef intrusive::slist_member_hook<
+ intrusive::tag< terminated_tag >,
+ intrusive::link_mode<
+ intrusive::safe_link
+ >
> terminated_hook;
-struct worker_tag;
-typedef intrusive::list_member_hook<
- intrusive::tag< worker_tag >,
+struct remote_ready_tag;
+typedef intrusive::slist_member_hook<
+ intrusive::tag< remote_ready_tag >,
intrusive::link_mode<
- intrusive::auto_unlink
+ intrusive::safe_link
>
-> worker_hook;
+> remote_ready_hook;
}
@@ -125,13 +142,17 @@ struct worker_context_t {};
const worker_context_t worker_context{};
class BOOST_FIBERS_DECL context {
+public:
+ typedef intrusive::slist<
+ context,
+ intrusive::function_hook< detail::wait_functor >,
+ intrusive::linear< true >,
+ intrusive::cache_last< true >
+ > wait_queue_t;
+
private:
friend class scheduler;
- enum flag_t {
- flag_terminated = 1 << 1
- };
-
struct fss_data {
void * vp{ nullptr };
detail::fss_cleanup_function::ptr_t cleanup_function{};
@@ -151,100 +172,102 @@ private:
}
};
- typedef std::map< uintptr_t, fss_data > fss_data_t;
+ typedef std::map< uintptr_t, fss_data > fss_data_t;
#if ! defined(BOOST_FIBERS_NO_ATOMICS)
- std::atomic< std::size_t > use_count_{ 0 };
- std::atomic< unsigned int > flags_;
- std::atomic< type > type_;
- std::atomic< scheduler * > scheduler_{ nullptr };
+ alignas(cache_alignment) std::atomic< std::size_t > use_count_{ 0 };
#else
- std::size_t use_count_{ 0 };
- unsigned int flags_;
- type type_;
- scheduler * scheduler_{ nullptr };
+ alignas(cache_alignment) std::size_t use_count_{ 0 };
+#endif
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
+ alignas(cache_alignment) detail::remote_ready_hook remote_ready_hook_{};
+ std::atomic< context * > remote_nxt_{ nullptr };
#endif
- launch policy_{ launch::post };
+ alignas(cache_alignment) detail::spinlock splk_{};
+ bool terminated_{ false };
+ wait_queue_t wait_queue_{};
+public:
+ detail::wait_hook wait_hook_{};
+private:
+ alignas(cache_alignment) 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_;
+ boost::context::execution_context ctx_;
#else
- boost::context::execution_context< detail::data_t * > ctx_;
+ boost::context::continuation c_;
#endif
+ fiber_properties * properties_{ nullptr };
+ std::chrono::steady_clock::time_point tp_{ (std::chrono::steady_clock::time_point::max)() };
+ type type_;
+ launch policy_;
void resume_( detail::data_t &) noexcept;
- void set_ready_( context *) 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 set_terminated()
+ // 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()->set_ready_( 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
- set_terminated();
+ terminate();
BOOST_ASSERT_MSG( false, "fiber already terminated");
}
#else
template< typename Fn, typename Tpl >
- boost::context::execution_context< detail::data_t * >
- run_( boost::context::execution_context< detail::data_t * > && ctx, Fn && fn_, Tpl && tpl_, detail::data_t * dp) noexcept {
+ boost::context::continuation
+ run_( boost::context::continuation && c, Fn && fn_, Tpl && tpl_) noexcept {
{
- // fn and tpl must be destroyed before calling set_terminated()
+ // 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_);
- // update execution_context of calling fiber
- dp->from->ctx_ = std::move( ctx);
+ 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()->set_ready_( 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 set_terminated();
+ return terminate();
}
#endif
public:
- detail::ready_hook ready_hook_{};
- detail::sleep_hook sleep_hook_{};
- detail::terminated_hook terminated_hook_{};
- detail::wait_hook wait_hook_{};
- detail::worker_hook worker_hook_{};
- std::atomic< context * > remote_nxt_{ nullptr };
- std::chrono::steady_clock::time_point tp_{ (std::chrono::steady_clock::time_point::max)() };
-
- typedef intrusive::list<
- context,
- intrusive::function_hook< detail::wait_functor >,
- intrusive::constant_time_size< false > > wait_queue_t;
-
-private:
- fss_data_t fss_data_{};
- wait_queue_t wait_queue_{};
- detail::spinlock splk_{};
- fiber_properties * properties_{ nullptr };
-
-public:
class id {
private:
context * impl_{ nullptr };
public:
- id() noexcept {
- }
+ id() = default;
explicit id( context * impl) noexcept :
- impl_( impl) {
+ impl_{ impl } {
}
bool operator==( id const& other) const noexcept {
@@ -311,9 +334,6 @@ public:
boost::context::preallocated palloc, StackAlloc salloc,
Fn && fn, Tpl && tpl) :
use_count_{ 1 }, // fiber instance or scheduler owner
- flags_{ 0 },
- type_{ type::worker_context },
- policy_{ policy },
#if (BOOST_EXECUTION_CONTEXT==1)
# if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
ctx_{ std::allocator_arg, palloc, salloc,
@@ -325,50 +345,66 @@ public:
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)
- 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< detail::data_t * > && ctx, detail::data_t * dp) mutable noexcept {
- return run_( std::forward< boost::context::execution_context< detail::data_t * > >( ctx), std::move( fn), std::move( tpl), dp);
- },
- std::forward< Fn >( fn),
- std::forward< Tpl >( tpl) )}
-
+ 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
- ctx_{ std::allocator_arg, palloc, salloc,
- [this,fn=detail::decay_copy( std::forward< Fn >( fn) ),tpl=std::forward< Tpl >( tpl)]
- (boost::context::execution_context< detail::data_t * > && ctx, detail::data_t * dp) mutable noexcept {
- return run_( std::forward< boost::context::execution_context< detail::data_t * > >( ctx), std::move( fn), std::move( tpl), dp);
- }}
+ 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;
+ friend bool
+ operator==( context const& lhs, context const& rhs) noexcept {
+ return & lhs == & rhs;
+ }
+
virtual ~context();
scheduler * get_scheduler() const noexcept {
-#if ! defined(BOOST_FIBERS_NO_ATOMICS)
- return scheduler_.load( std::memory_order_relaxed);
-#else
return scheduler_;
-#endif
}
id get_id() const noexcept;
+ bool is_resumable() const noexcept {
+ if ( c_) return true;
+ else return false;
+ }
+
void resume() noexcept;
void resume( detail::spinlock_lock &) noexcept;
void resume( context *) noexcept;
@@ -377,10 +413,10 @@ public:
void suspend( detail::spinlock_lock &) noexcept;
#if (BOOST_EXECUTION_CONTEXT==1)
- void set_terminated() noexcept;
+ void terminate() noexcept;
#else
- boost::context::execution_context< detail::data_t * > suspend_with_cc() noexcept;
- boost::context::execution_context< detail::data_t * > set_terminated() noexcept;
+ boost::context::continuation suspend_with_cc() noexcept;
+ boost::context::continuation terminate() noexcept;
#endif
void join();
@@ -390,16 +426,12 @@ public:
bool wait_until( std::chrono::steady_clock::time_point const&,
detail::spinlock_lock &) noexcept;
- void set_ready( context *) noexcept;
+ void schedule( context *) noexcept;
bool is_context( type t) const noexcept {
return type::none != ( type_ & t);
}
- bool is_terminated() const noexcept {
- return 0 != ( flags_ & flag_terminated);
- }
-
void * get_fss_data( void const * vp) const;
void set_fss_data(
@@ -418,77 +450,90 @@ public:
return policy_;
}
+ bool worker_is_linked() const noexcept;
+
bool ready_is_linked() const noexcept;
+ bool remote_ready_is_linked() const noexcept;
+
bool sleep_is_linked() const noexcept;
bool terminated_is_linked() const noexcept;
bool wait_is_linked() const noexcept;
- bool worker_is_linked() const noexcept;
+ template< typename List >
+ void worker_link( List & lst) noexcept {
+ static_assert( std::is_same< typename List::value_traits::hook_type, detail::worker_hook >::value, "not a worker-queue");
+ BOOST_ASSERT( ! worker_is_linked() );
+ lst.push_back( * this);
+ }
template< typename List >
void ready_link( List & lst) noexcept {
static_assert( std::is_same< typename List::value_traits::hook_type, detail::ready_hook >::value, "not a ready-queue");
+ BOOST_ASSERT( ! ready_is_linked() );
+ lst.push_back( * this);
+ }
+
+ template< typename List >
+ void remote_ready_link( List & lst) noexcept {
+ static_assert( std::is_same< typename List::value_traits::hook_type, detail::remote_ready_hook >::value, "not a remote-ready-queue");
+ BOOST_ASSERT( ! remote_ready_is_linked() );
lst.push_back( * this);
}
template< typename Set >
void sleep_link( Set & set) noexcept {
static_assert( std::is_same< typename Set::value_traits::hook_type,detail::sleep_hook >::value, "not a sleep-queue");
+ BOOST_ASSERT( ! sleep_is_linked() );
set.insert( * this);
}
template< typename List >
void terminated_link( List & lst) noexcept {
static_assert( std::is_same< typename List::value_traits::hook_type, detail::terminated_hook >::value, "not a terminated-queue");
+ BOOST_ASSERT( ! terminated_is_linked() );
lst.push_back( * this);
}
template< typename List >
void wait_link( List & lst) noexcept {
static_assert( std::is_same< typename List::value_traits::hook_type, detail::wait_hook >::value, "not a wait-queue");
+ BOOST_ASSERT( ! wait_is_linked() );
lst.push_back( * this);
}
- template< typename List >
- void worker_link( List & lst) noexcept {
- static_assert( std::is_same< typename List::value_traits::hook_type, detail::worker_hook >::value, "not a worker-queue");
- lst.push_back( * this);
- }
+ void worker_unlink() noexcept;
void ready_unlink() noexcept;
void sleep_unlink() noexcept;
- void wait_unlink() noexcept;
-
- void worker_unlink() noexcept;
-
void detach() noexcept;
void attach( context *) noexcept;
friend void intrusive_ptr_add_ref( context * ctx) noexcept {
BOOST_ASSERT( nullptr != ctx);
- ++ctx->use_count_;
+ ctx->use_count_.fetch_add( 1, std::memory_order_relaxed);
}
friend void intrusive_ptr_release( context * ctx) noexcept {
BOOST_ASSERT( nullptr != ctx);
- if ( 0 == --ctx->use_count_) {
+ 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_);
+ boost::context::execution_context ec = ctx->ctx_;
// destruct context
// deallocates stack (execution_context is ref counted)
ctx->~context();
#else
- boost::context::execution_context< detail::data_t * > cc( std::move( ctx->ctx_) );
+ boost::context::continuation c = std::move( ctx->c_);
// destruct context
ctx->~context();
// deallocated stack
- cc( nullptr);
+ c.resume( nullptr);
#endif
}
}
@@ -521,14 +566,14 @@ static intrusive_ptr< context > make_worker_context( launch policy,
const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
#endif
// placement new of context on top of fiber's stack
- return intrusive_ptr< context >(
- ::new ( sp) context(
+ return intrusive_ptr< context >{
+ ::new ( sp) context{
worker_context,
policy,
- boost::context::preallocated( sp, size, sctx),
+ boost::context::preallocated{ sp, size, sctx },
salloc,
std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ... ) ) );
+ std::make_tuple( std::forward< Args >( args) ... ) } };
}
namespace detail {
diff --git a/boost/fiber/detail/config.hpp b/boost/fiber/detail/config.hpp
index f65d48910d..7c7119e1fb 100644
--- a/boost/fiber/detail/config.hpp
+++ b/boost/fiber/detail/config.hpp
@@ -52,7 +52,7 @@
#endif
#if !defined(BOOST_FIBERS_SPIN_MAX_TESTS)
-# define BOOST_FIBERS_SPIN_MAX_TESTS 100
+# define BOOST_FIBERS_SPIN_MAX_TESTS 500
#endif
// modern architectures have cachelines with 64byte length
diff --git a/boost/fiber/detail/context_mpsc_queue.hpp b/boost/fiber/detail/context_mpsc_queue.hpp
deleted file mode 100644
index f7e664659c..0000000000
--- a/boost/fiber/detail/context_mpsc_queue.hpp
+++ /dev/null
@@ -1,98 +0,0 @@
-
-// Copyright Dmitry Vyukov 2010-2011.
-// Copyright Oliver Kowalke 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)
-//
-// based on Dmitry Vyukov's intrusive MPSC queue
-// http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue
-// https://groups.google.com/forum/#!topic/lock-free/aFHvZhu1G-0
-
-#ifndef BOOST_FIBERS_DETAIL_CONTEXT_MPSC_QUEUE_H
-#define BOOST_FIBERS_DETAIL_CONTEXT_MPSC_QUEUE_H
-
-#include <atomic>
-#include <memory>
-#include <type_traits>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-
-#include <boost/fiber/context.hpp>
-#include <boost/fiber/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace fibers {
-namespace detail {
-
-// a MPSC queue
-// multiple threads push ready fibers (belonging to local scheduler)
-// (thread) local scheduler pops fibers
-class context_mpsc_queue {
-private:
- // not default constructor for context - use aligned_storage instead
- alignas(cache_alignment) std::aligned_storage< sizeof( context), alignof( context) >::type storage_{};
- context * dummy_;
- alignas(cache_alignment) std::atomic< context * > head_;
- alignas(cache_alignment) context * tail_;
- char pad_[cacheline_length];
-
-public:
- context_mpsc_queue() :
- dummy_{ reinterpret_cast< context * >( std::addressof( storage_) ) },
- head_{ dummy_ },
- tail_{ dummy_ } {
- dummy_->remote_nxt_.store( nullptr, std::memory_order_release);
- }
-
- context_mpsc_queue( context_mpsc_queue const&) = delete;
- context_mpsc_queue & operator=( context_mpsc_queue const&) = delete;
-
- void push( context * ctx) noexcept {
- BOOST_ASSERT( nullptr != ctx);
- ctx->remote_nxt_.store( nullptr, std::memory_order_release);
- context * prev = head_.exchange( ctx, std::memory_order_acq_rel);
- prev->remote_nxt_.store( ctx, std::memory_order_release);
- }
-
- context * pop() noexcept {
- context * tail = tail_;
- context * next = tail->remote_nxt_.load( std::memory_order_acquire);
- if ( dummy_ == tail) {
- if ( nullptr == next) {
- return nullptr;
- }
- tail_ = next;
- tail = next;
- next = next->remote_nxt_.load( std::memory_order_acquire);;
- }
- if ( nullptr != next) {
- tail_ = next;
- return tail;
- }
- context * head = head_.load( std::memory_order_acquire);
- if ( tail != head) {
- return nullptr;
- }
- push( dummy_);
- next = tail->remote_nxt_.load( std::memory_order_acquire);
- if ( nullptr != next) {
- tail_= next;
- return tail;
- }
- return nullptr;
- }
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_FIBERS_DETAIL_CONTEXT_MPSC_QUEUE_H
diff --git a/boost/fiber/detail/context_spinlock_queue.hpp b/boost/fiber/detail/context_spinlock_queue.hpp
new file mode 100644
index 0000000000..e0ebdabda6
--- /dev/null
+++ b/boost/fiber/detail/context_spinlock_queue.hpp
@@ -0,0 +1,118 @@
+
+// Copyright Oliver Kowalke 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_FIBERS_DETAIL_SPINLOCK_QUEUE_H
+#define BOOST_FIBERS_DETAIL_SPINLOCK_QUEUE_H
+
+#include <cstddef>
+#include <cstring>
+#include <mutex>
+
+#include <boost/config.hpp>
+
+#include <boost/fiber/context.hpp>
+#include <boost/fiber/detail/config.hpp>
+#include <boost/fiber/detail/spinlock.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+class context_spinlock_queue {
+private:
+ typedef context * slot_type;
+
+ alignas(cache_alignment) mutable spinlock splk_{};
+ std::size_t pidx_{ 0 };
+ std::size_t cidx_{ 0 };
+ std::size_t capacity_;
+ slot_type * slots_;
+
+ void resize_() {
+ slot_type * old_slots = slots_;
+ slots_ = new slot_type[2*capacity_];
+ std::size_t offset = capacity_ - cidx_;
+ std::memcpy( slots_, old_slots + cidx_, offset * sizeof( slot_type) );
+ if ( 0 < cidx_) {
+ std::memcpy( slots_ + offset, old_slots, pidx_ * sizeof( slot_type) );
+ }
+ cidx_ = 0;
+ pidx_ = capacity_ - 1;
+ capacity_ *= 2;
+ delete [] old_slots;
+ }
+
+ bool is_full_() const noexcept {
+ return cidx_ == ((pidx_ + 1) % capacity_);
+ }
+
+ bool is_empty_() const noexcept {
+ return cidx_ == pidx_;
+ }
+
+public:
+ context_spinlock_queue( std::size_t capacity = 4096) :
+ capacity_{ capacity } {
+ slots_ = new slot_type[capacity_];
+ }
+
+ ~context_spinlock_queue() {
+ delete [] slots_;
+ }
+
+ context_spinlock_queue( context_spinlock_queue const&) = delete;
+ context_spinlock_queue & operator=( context_spinlock_queue const&) = delete;
+
+ bool empty() const noexcept {
+ spinlock_lock lk{ splk_ };
+ return is_empty_();
+ }
+
+ void push( context * c) {
+ spinlock_lock lk{ splk_ };
+ if ( is_full_() ) {
+ resize_();
+ }
+ slots_[pidx_] = c;
+ pidx_ = (pidx_ + 1) % capacity_;
+ }
+
+ context * pop() {
+ spinlock_lock lk{ splk_ };
+ context * c = nullptr;
+ if ( ! is_empty_() ) {
+ c = slots_[cidx_];
+ cidx_ = (cidx_ + 1) % capacity_;
+ }
+ return c;
+ }
+
+ context * steal() {
+ spinlock_lock lk{ splk_ };
+ context * c = nullptr;
+ if ( ! is_empty_() ) {
+ c = slots_[cidx_];
+ if ( c->is_context( type::pinned_context) ) {
+ return nullptr;
+ }
+ cidx_ = (cidx_ + 1) % capacity_;
+ }
+ return c;
+ }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_FIBERS_DETAIL_SPINLOCK_QUEUE_H
diff --git a/boost/fiber/detail/context_spmc_queue.hpp b/boost/fiber/detail/context_spmc_queue.hpp
index 6449e3658f..27256233cf 100644
--- a/boost/fiber/detail/context_spmc_queue.hpp
+++ b/boost/fiber/detail/context_spmc_queue.hpp
@@ -30,6 +30,11 @@
// In Proceedings of the 18th ACM SIGPLAN symposium on Principles and practice
// of parallel programming (PPoPP '13). ACM, New York, NY, USA, 69-80.
+#if BOOST_COMP_CLANG
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-private-field"
+#endif
+
namespace boost {
namespace fibers {
namespace detail {
@@ -43,43 +48,43 @@ private:
sizeof( atomic_type), cache_alignment
>::type storage_type;
- std::size_t size_;
+ std::size_t capacity_;
storage_type * storage_;
public:
- array( std::size_t size) :
- size_{ size },
- storage_{ new storage_type[size_] } {
- for ( std::size_t i = 0; i < size_; ++i) {
+ array( std::size_t capacity) :
+ capacity_{ capacity },
+ storage_{ new storage_type[capacity_] } {
+ for ( std::size_t i = 0; i < capacity_; ++i) {
::new ( static_cast< void * >( std::addressof( storage_[i]) ) ) atomic_type{ nullptr };
}
}
~array() {
- for ( std::size_t i = 0; i < size_; ++i) {
+ for ( std::size_t i = 0; i < capacity_; ++i) {
reinterpret_cast< atomic_type * >( std::addressof( storage_[i]) )->~atomic_type();
}
delete [] storage_;
}
- std::size_t size() const noexcept {
- return size_;
+ std::size_t capacity() const noexcept {
+ return capacity_;
}
void push( std::size_t bottom, context * ctx) noexcept {
reinterpret_cast< atomic_type * >(
- std::addressof( storage_[bottom % size_]) )
+ std::addressof( storage_[bottom % capacity_]) )
->store( ctx, std::memory_order_relaxed);
}
context * pop( std::size_t top) noexcept {
return reinterpret_cast< atomic_type * >(
- std::addressof( storage_[top % size_]) )
+ std::addressof( storage_[top % capacity_]) )
->load( std::memory_order_relaxed);
}
array * resize( std::size_t bottom, std::size_t top) {
- std::unique_ptr< array > tmp{ new array{ 2 * size_ } };
+ std::unique_ptr< array > tmp{ new array{ 2 * capacity_ } };
for ( std::size_t i = top; i != bottom; ++i) {
tmp->push( i, pop( i) );
}
@@ -87,15 +92,15 @@ 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< std::size_t > top_{ 0 };
+ alignas(cache_alignment) std::atomic< std::size_t > bottom_{ 0 };
alignas(cache_alignment) std::atomic< array * > array_;
- std::vector< array * > old_arrays_{};
+ std::vector< array * > old_arrays_{};
char padding_[cacheline_length];
public:
- context_spmc_queue() :
- array_{ new array{ 1024 } } {
+ context_spmc_queue( std::size_t capacity = 4096) :
+ array_{ new array{ capacity } } {
old_arrays_.reserve( 32);
}
@@ -110,19 +115,19 @@ public:
context_spmc_queue & operator=( context_spmc_queue const&) = delete;
bool empty() const noexcept {
- std::size_t bottom{ bottom_.load( std::memory_order_relaxed) };
- std::size_t top{ top_.load( std::memory_order_relaxed) };
+ std::size_t bottom = bottom_.load( std::memory_order_relaxed);
+ std::size_t top = top_.load( std::memory_order_relaxed);
return bottom <= top;
}
void push( context * ctx) {
- std::size_t bottom{ bottom_.load( std::memory_order_relaxed) };
- std::size_t top{ top_.load( std::memory_order_acquire) };
- array * a{ array_.load( std::memory_order_relaxed) };
- if ( (a->size() - 1) < (bottom - top) ) {
+ std::size_t bottom = bottom_.load( std::memory_order_relaxed);
+ std::size_t top = top_.load( std::memory_order_acquire);
+ array * a = array_.load( std::memory_order_relaxed);
+ if ( (a->capacity() - 1) < (bottom - top) ) {
// queue is full
// resize
- array * tmp{ a->resize( bottom, top) };
+ array * tmp = a->resize( bottom, top);
old_arrays_.push_back( a);
std::swap( a, tmp);
array_.store( a, std::memory_order_relaxed);
@@ -133,16 +138,48 @@ public:
}
context * pop() {
- std::size_t top{ top_.load( std::memory_order_acquire) };
+ std::size_t bottom = bottom_.load( std::memory_order_relaxed) - 1;
+ array * a = array_.load( std::memory_order_relaxed);
+ bottom_.store( bottom, std::memory_order_relaxed);
std::atomic_thread_fence( std::memory_order_seq_cst);
- std::size_t bottom{ bottom_.load( std::memory_order_acquire) };
- context * ctx{ nullptr };
+ std::size_t top = top_.load( std::memory_order_relaxed);
+ context * ctx = nullptr;
+ if ( top <= bottom) {
+ // queue is not empty
+ ctx = a->pop( bottom);
+ BOOST_ASSERT( nullptr != ctx);
+ if ( top == bottom) {
+ // last element dequeued
+ if ( ! top_.compare_exchange_strong( top, top + 1,
+ std::memory_order_seq_cst,
+ std::memory_order_relaxed) ) {
+ // lose the race
+ ctx = nullptr;
+ }
+ bottom_.store( bottom + 1, std::memory_order_relaxed);
+ }
+ } else {
+ // queue is empty
+ bottom_.store( bottom + 1, std::memory_order_relaxed);
+ }
+ return ctx;
+ }
+
+ context * steal() {
+ std::size_t top = top_.load( std::memory_order_acquire);
+ std::atomic_thread_fence( std::memory_order_seq_cst);
+ std::size_t bottom = bottom_.load( std::memory_order_acquire);
+ context * ctx = nullptr;
if ( top < bottom) {
// queue is not empty
- array * a{ array_.load( std::memory_order_consume) };
+ array * a = array_.load( std::memory_order_consume);
ctx = a->pop( top);
- if ( ctx->is_context( type::pinned_context) ||
- ! top_.compare_exchange_strong( top, top + 1,
+ BOOST_ASSERT( nullptr != ctx);
+ // do not steal pinned context (e.g. main-/dispatcher-context)
+ if ( ctx->is_context( type::pinned_context) ) {
+ return nullptr;
+ }
+ if ( ! top_.compare_exchange_strong( top, top + 1,
std::memory_order_seq_cst,
std::memory_order_relaxed) ) {
// lose the race
@@ -155,4 +192,8 @@ public:
}}}
+#if BOOST_COMP_CLANG
+#pragma clang diagnostic pop
+#endif
+
#endif // BOOST_FIBERS_DETAIL_CONTEXT_SPMC_QUEUE_H
diff --git a/boost/fiber/detail/cpu_relax.hpp b/boost/fiber/detail/cpu_relax.hpp
index d00020a23b..541b46dfd0 100644
--- a/boost/fiber/detail/cpu_relax.hpp
+++ b/boost/fiber/detail/cpu_relax.hpp
@@ -7,6 +7,7 @@
#ifndef BOOST_FIBERS_DETAIL_CPU_RELAX_H
#define BOOST_FIBERS_DETAIL_CPU_RELAX_H
+#include <chrono>
#include <thread>
#include <boost/config.hpp>
@@ -14,7 +15,7 @@
#include <boost/fiber/detail/config.hpp>
-#if BOOST_COMP_MSVC
+#if BOOST_COMP_MSVC || BOOST_COMP_MSVC_EMULATED
# include <Windows.h>
#endif
@@ -29,22 +30,47 @@ namespace detail {
#if BOOST_ARCH_ARM
# if BOOST_COMP_MSVC
# define cpu_relax() YieldProcessor();
-# else
+# elif (defined(__ARM_ARCH_6K__) || \
+ defined(__ARM_ARCH_6Z__) || \
+ defined(__ARM_ARCH_6ZK__) || \
+ defined(__ARM_ARCH_6T2__) || \
+ defined(__ARM_ARCH_7__) || \
+ defined(__ARM_ARCH_7A__) || \
+ defined(__ARM_ARCH_7R__) || \
+ defined(__ARM_ARCH_7M__) || \
+ defined(__ARM_ARCH_7S__) || \
+ defined(__ARM_ARCH_8A__) || \
+ defined(__aarch64__))
+// http://groups.google.com/a/chromium.org/forum/#!msg/chromium-dev/YGVrZbxYOlU/Vpgy__zeBQAJ
+// mnemonic 'yield' is supported from ARMv6k onwards
# define cpu_relax() asm volatile ("yield" ::: "memory");
+# else
+# define cpu_relax() asm volatile ("nop" ::: "memory");
# endif
#elif BOOST_ARCH_MIPS
# define cpu_relax() asm volatile ("pause" ::: "memory");
#elif BOOST_ARCH_PPC
+// http://code.metager.de/source/xref/gnu/glibc/sysdeps/powerpc/sys/platform/ppc.h
+// http://stackoverflow.com/questions/5425506/equivalent-of-x86-pause-instruction-for-ppc
+// mnemonic 'or' shared resource hints
+// or 27, 27, 27 This form of 'or' provides a hint that performance
+// will probably be imrpoved if shared resources dedicated
+// to the executing processor are released for use by other
+// processors
+// extended mnemonics (available with POWER7)
+// yield == or 27, 27, 27
# define cpu_relax() asm volatile ("or 27,27,27" ::: "memory");
#elif BOOST_ARCH_X86
-# if BOOST_COMP_MSVC
+# if BOOST_COMP_MSVC || BOOST_COMP_MSVC_EMULATED
# define cpu_relax() YieldProcessor();
# else
# define cpu_relax() asm volatile ("pause" ::: "memory");
# endif
#else
-# warning "architecture does not support yield/pause mnemonic"
-# define cpu_relax() std::this_thread::yield();
+# define cpu_relax() { \
+ static constexpr std::chrono::microseconds us0{ 0 }; \
+ std::this_thread::sleep_for( us0); \
+ }
#endif
}}}
diff --git a/boost/fiber/detail/data.hpp b/boost/fiber/detail/data.hpp
index 24e833a9e8..e2b119ec3e 100644
--- a/boost/fiber/detail/data.hpp
+++ b/boost/fiber/detail/data.hpp
@@ -28,7 +28,7 @@ struct data_t {
spinlock_lock * lk{ nullptr };
context * ctx{ nullptr };
- data_t() noexcept = default;
+ data_t() = default;
explicit data_t( spinlock_lock * lk_) noexcept :
lk{ lk_ } {
diff --git a/boost/fiber/detail/fss.hpp b/boost/fiber/detail/fss.hpp
index 54dc5b79d3..27a7d67f26 100644
--- a/boost/fiber/detail/fss.hpp
+++ b/boost/fiber/detail/fss.hpp
@@ -38,12 +38,13 @@ public:
friend inline
void intrusive_ptr_add_ref( fss_cleanup_function * p) noexcept {
- ++p->use_count_;
+ p->use_count_.fetch_add( 1, std::memory_order_relaxed);
}
friend inline
void intrusive_ptr_release( fss_cleanup_function * p) noexcept {
- if ( --p->use_count_ == 0) {
+ if ( 1 == p->use_count_.fetch_sub( 1, std::memory_order_release) ) {
+ std::atomic_thread_fence( std::memory_order_acquire);
delete p;
}
}
diff --git a/boost/fiber/detail/futex.hpp b/boost/fiber/detail/futex.hpp
index 4c966867c5..d383dc4077 100644
--- a/boost/fiber/detail/futex.hpp
+++ b/boost/fiber/detail/futex.hpp
@@ -49,7 +49,7 @@ int futex_wake( std::atomic< std::int32_t > * addr) {
inline
int futex_wait( std::atomic< std::int32_t > * addr, std::int32_t x) {
- ::WaitOnAddress( static_cast< volatile void * >( addr), & x, sizeof( x), -1);
+ ::WaitOnAddress( static_cast< volatile void * >( addr), & x, sizeof( x), INFINITE);
return 0;
}
#else
diff --git a/boost/fiber/detail/spinlock_ttas.hpp b/boost/fiber/detail/spinlock_ttas.hpp
index d64630d84d..380773ad6d 100644
--- a/boost/fiber/detail/spinlock_ttas.hpp
+++ b/boost/fiber/detail/spinlock_ttas.hpp
@@ -19,6 +19,11 @@
// 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 {
@@ -30,10 +35,7 @@ private:
unlocked
};
- // align shared variable 'state_' at cache line to prevent false sharing
- alignas(cache_alignment) std::atomic< spinlock_status > state_{ spinlock_status::unlocked };
- // padding to avoid other data one the cacheline of shared variable 'state_'
- char pad[cacheline_length];
+ std::atomic< spinlock_status > state_{ spinlock_status::unlocked };
public:
spinlock_ttas() noexcept = default;
@@ -63,20 +65,15 @@ public:
// 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_MAX_TESTS + 20 > tests) {
- ++tests;
+ } else {
// 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();
@@ -89,10 +86,12 @@ public:
// 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;
- const std::size_t z =
- std::uniform_int_distribution< std::size_t >{ 0, static_cast< std::size_t >( 1) << collisions }( generator);
+ static std::uniform_int_distribution< std::size_t > distribution{ 0, static_cast< std::size_t >( 1) << collisions };
+ const std::size_t z = distribution( generator);
++collisions;
for ( std::size_t i = 0; i < z; ++i) {
+ // -> reduces the power consumed by the CPU
+ // -> prevent pipeline stalls
cpu_relax();
}
} else {
@@ -109,4 +108,8 @@ 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 c6a9a57d79..da044b6298 100644
--- a/boost/fiber/detail/spinlock_ttas_adaptive.hpp
+++ b/boost/fiber/detail/spinlock_ttas_adaptive.hpp
@@ -31,11 +31,8 @@ private:
unlocked
};
- // align shared variable 'state_' at cache line to prevent false sharing
- alignas(cache_alignment) std::atomic< spinlock_status > state_{ spinlock_status::unlocked };
- std::atomic< std::size_t > tests_{ 0 };
- // padding to avoid other data one the cacheline of shared variable 'state_'
- char pad[cacheline_length];
+ std::atomic< spinlock_status > state_{ spinlock_status::unlocked };
+ std::atomic< std::size_t > tests_{ 0 };
public:
spinlock_ttas_adaptive() noexcept = default;
@@ -67,8 +64,9 @@ public:
// 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_MAX_TESTS + 20 > tests) {
+ } else {
++tests;
// 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
@@ -76,11 +74,6 @@ public:
// 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();
@@ -93,10 +86,12 @@ public:
// 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;
- const std::size_t z =
- std::uniform_int_distribution< std::size_t >{ 0, static_cast< std::size_t >( 1) << collisions }( generator);
+ static std::uniform_int_distribution< std::size_t > distribution{ 0, static_cast< std::size_t >( 1) << collisions };
+ const std::size_t z = distribution( generator);
++collisions;
for ( std::size_t i = 0; i < z; ++i) {
+ // -> reduces the power consumed by the CPU
+ // -> prevent pipeline stalls
cpu_relax();
}
} else {
diff --git a/boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp b/boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp
index fbd6a0e4d2..61ab47691e 100644
--- a/boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp
+++ b/boost/fiber/detail/spinlock_ttas_adaptive_futex.hpp
@@ -26,11 +26,8 @@ namespace detail {
class spinlock_ttas_adaptive_futex {
private:
- // align shared variable 'value_' at cache line to prevent false sharing
- alignas(cache_alignment) std::atomic< std::int32_t > value_{ 0 };
- std::atomic< std::int32_t > tests_{ 0 };
- // padding to avoid other data one the cacheline of shared variable 'value_'
- char pad_[cacheline_length];
+ std::atomic< std::int32_t > value_{ 0 };
+ std::atomic< std::int32_t > tests_{ 0 };
public:
spinlock_ttas_adaptive_futex() noexcept = default;
@@ -61,6 +58,7 @@ public:
// 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
// std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
@@ -73,10 +71,12 @@ public:
// 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;
- const std::int32_t z = std::uniform_int_distribution< std::int32_t >{
- 0, static_cast< std::int32_t >( 1) << collisions }( generator);
+ static std::uniform_int_distribution< std::int32_t > distribution{ 0, static_cast< std::int32_t >( 1) << collisions };
+ const std::int32_t z = distribution( generator);
++collisions;
for ( std::int32_t i = 0; i < z; ++i) {
+ // -> reduces the power consumed by the CPU
+ // -> prevent pipeline stalls
cpu_relax();
}
} else {
diff --git a/boost/fiber/detail/spinlock_ttas_futex.hpp b/boost/fiber/detail/spinlock_ttas_futex.hpp
index b11e63b587..a427b73ba5 100644
--- a/boost/fiber/detail/spinlock_ttas_futex.hpp
+++ b/boost/fiber/detail/spinlock_ttas_futex.hpp
@@ -25,10 +25,7 @@ namespace detail {
class spinlock_ttas_futex {
private:
- // align shared variable 'value_' at cache line to prevent false sharing
- alignas(cache_alignment) std::atomic< std::int32_t > value_{ 0 };
- // padding to avoid other data one the cacheline of shared variable 'value_'
- char pad_[cacheline_length];
+ std::atomic< std::int32_t > value_{ 0 };
public:
spinlock_ttas_futex() noexcept = default;
@@ -57,6 +54,7 @@ public:
// 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
// std::this_thread::yield() allows this_thread to give up the remaining part of its time slice,
@@ -69,10 +67,12 @@ public:
// 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;
- const std::int32_t z = std::uniform_int_distribution< std::int32_t >{
- 0, static_cast< std::int32_t >( 1) << collisions }( generator);
+ static std::uniform_int_distribution< std::int32_t > distribution{ 0, static_cast< std::int32_t >( 1) << collisions };
+ const std::int32_t z = distribution( generator);
++collisions;
for ( std::int32_t i = 0; i < z; ++i) {
+ // -> reduces the power consumed by the CPU
+ // -> prevent pipeline stalls
cpu_relax();
}
} else {
diff --git a/boost/fiber/detail/wrap.hpp b/boost/fiber/detail/wrap.hpp
index 0369e61ee6..558de6bd94 100644
--- a/boost/fiber/detail/wrap.hpp
+++ b/boost/fiber/detail/wrap.hpp
@@ -10,8 +10,14 @@
#include <type_traits>
#include <boost/config.hpp>
+#if defined(BOOST_NO_CXX17_STD_INVOKE)
#include <boost/context/detail/invoke.hpp>
-#include <boost/context/execution_context.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>
@@ -36,9 +42,9 @@ private:
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) ),
+ fn1_{ std::move( fn1) },
+ fn2_{ std::move( fn2) },
+ tpl_{ std::move( tpl) },
ctx_{ ctx } {
}
@@ -49,9 +55,11 @@ public:
wrapper & operator=( wrapper && other) = default;
void operator()( void * vp) {
- boost::context::detail::invoke(
- std::move( fn1_),
- fn2_, tpl_, ctx_, 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
}
};
@@ -59,11 +67,11 @@ 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 >(
+ return wrapper< Fn1, Fn2, Tpl >{
std::forward< Fn1 >( fn1),
std::forward< Fn2 >( fn2),
std::forward< Tpl >( tpl),
- ctx);
+ ctx };
}
#else
template< typename Fn1, typename Fn2, typename Tpl >
@@ -75,9 +83,9 @@ private:
public:
wrapper( Fn1 && fn1, Fn2 && fn2, Tpl && tpl) :
- fn1_( std::move( fn1) ),
- fn2_( std::move( fn2) ),
- tpl_( std::move( tpl) ) {
+ fn1_{ std::move( fn1) },
+ fn2_{ std::move( fn2) },
+ tpl_{ std::move( tpl) } {
}
wrapper( wrapper const&) = delete;
@@ -86,24 +94,31 @@ public:
wrapper( wrapper && other) = default;
wrapper & operator=( wrapper && other) = default;
- boost::context::execution_context< data_t * >
- operator()( boost::context::execution_context< data_t * > && ctx, data_t * dp) {
+ 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::execution_context< data_t * > >( ctx),
- dp);
+ 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 >(
+ return wrapper< Fn1, Fn2, Tpl >{
std::forward< Fn1 >( fn1),
std::forward< Fn2 >( fn2),
- std::forward< Tpl >( tpl) );
+ std::forward< Tpl >( tpl) };
}
#endif
diff --git a/boost/fiber/exceptions.hpp b/boost/fiber/exceptions.hpp
index ddbf45eadf..5a5f7e4f1b 100644
--- a/boost/fiber/exceptions.hpp
+++ b/boost/fiber/exceptions.hpp
@@ -28,15 +28,15 @@ namespace fibers {
class fiber_error : public std::system_error {
public:
fiber_error( std::error_code ec) :
- std::system_error( ec) {
+ std::system_error{ ec } {
}
fiber_error( std::error_code ec, const char * what_arg) :
- std::system_error( ec, what_arg) {
+ std::system_error{ ec, what_arg } {
}
fiber_error( std::error_code ec, std::string const& what_arg) :
- std::system_error( ec, what_arg) {
+ std::system_error{ ec, what_arg } {
}
virtual ~fiber_error() = default;
@@ -45,15 +45,15 @@ public:
class lock_error : public fiber_error {
public:
lock_error( std::error_code ec) :
- fiber_error( ec) {
+ fiber_error{ ec } {
}
lock_error( std::error_code ec, const char * what_arg) :
- fiber_error( ec, what_arg) {
+ fiber_error{ ec, what_arg } {
}
lock_error( std::error_code ec, std::string const& what_arg) :
- fiber_error( ec, what_arg) {
+ fiber_error{ ec, what_arg } {
}
};
@@ -77,12 +77,12 @@ struct is_error_code_enum< boost::fibers::future_errc > : public true_type {
inline
std::error_code make_error_code( boost::fibers::future_errc e) noexcept {
- return std::error_code( static_cast< int >( e), boost::fibers::future_category() );
+ return std::error_code{ static_cast< int >( e), boost::fibers::future_category() };
}
inline
std::error_condition make_error_condition( boost::fibers::future_errc e) noexcept {
- return std::error_condition( static_cast< int >( e), boost::fibers::future_category() );
+ return std::error_condition{ static_cast< int >( e), boost::fibers::future_category() };
}
}
@@ -93,49 +93,49 @@ namespace fibers {
class future_error : public fiber_error {
public:
future_error( std::error_code ec) :
- fiber_error( ec) {
+ fiber_error{ ec } {
}
};
class future_uninitialized : public future_error {
public:
future_uninitialized() :
- future_error( std::make_error_code( future_errc::no_state) ) {
+ future_error{ std::make_error_code( future_errc::no_state) } {
}
};
class future_already_retrieved : public future_error {
public:
future_already_retrieved() :
- future_error( std::make_error_code( future_errc::future_already_retrieved) ) {
+ future_error{ std::make_error_code( future_errc::future_already_retrieved) } {
}
};
class broken_promise : public future_error {
public:
broken_promise() :
- future_error( std::make_error_code( future_errc::broken_promise) ) {
+ future_error{ std::make_error_code( future_errc::broken_promise) } {
}
};
class promise_already_satisfied : public future_error {
public:
promise_already_satisfied() :
- future_error( std::make_error_code( future_errc::promise_already_satisfied) ) {
+ future_error{ std::make_error_code( future_errc::promise_already_satisfied) } {
}
};
class promise_uninitialized : public future_error {
public:
promise_uninitialized() :
- future_error( std::make_error_code( future_errc::no_state) ) {
+ future_error{ std::make_error_code( future_errc::no_state) } {
}
};
class packaged_task_uninitialized : public future_error {
public:
packaged_task_uninitialized() :
- future_error( std::make_error_code( future_errc::no_state) ) {
+ future_error{ std::make_error_code( future_errc::no_state) } {
}
};
diff --git a/boost/fiber/fiber.hpp b/boost/fiber/fiber.hpp
index 0fbc84ad12..1508a9b5a6 100644
--- a/boost/fiber/fiber.hpp
+++ b/boost/fiber/fiber.hpp
@@ -49,7 +49,7 @@ private:
public:
typedef context::id id;
- fiber() noexcept = default;
+ fiber() = default;
template< typename Fn,
typename ... Args,
@@ -108,7 +108,9 @@ public:
if ( joinable() ) {
std::terminate();
}
- if ( this == & other) return * this;
+ if ( this == & other) {
+ return * this;
+ }
impl_.swap( other.impl_);
return * this;
}
@@ -132,7 +134,7 @@ public:
template< typename PROPS >
PROPS & properties() {
auto props = impl_->get_properties();
- BOOST_ASSERT_MSG(props, "fiber::properties not set");
+ BOOST_ASSERT_MSG( props, "fiber::properties not set");
return dynamic_cast< PROPS & >( * props );
}
};
diff --git a/boost/fiber/fss.hpp b/boost/fiber/fss.hpp
index a578d40a7f..f65d7353b3 100644
--- a/boost/fiber/fss.hpp
+++ b/boost/fiber/fss.hpp
@@ -58,9 +58,9 @@ public:
}
~fiber_specific_ptr() {
- context * f = context::active();
- if ( nullptr != f) {
- f->set_fss_data(
+ context * active_ctx = context::active();
+ if ( nullptr != active_ctx) {
+ active_ctx->set_fss_data(
this, cleanup_fn_, nullptr, true);
}
}
diff --git a/boost/fiber/future/async.hpp b/boost/fiber/future/async.hpp
index d969d19ce3..e68b2c28fa 100644
--- a/boost/fiber/future/async.hpp
+++ b/boost/fiber/future/async.hpp
@@ -23,63 +23,85 @@ namespace fibers {
template< typename Fn, typename ... Args >
future<
- typename std::result_of<
- typename std::enable_if<
- ! detail::is_launch_policy< typename std::decay< Fn >::type >::value,
- typename std::decay< Fn >::type
- >::type( typename std::decay< Args >::type ... )
- >::type
+ typename std::result_of<
+ typename std::enable_if<
+ ! detail::is_launch_policy< typename std::decay< Fn >::type >::value,
+ typename std::decay< Fn >::type
+ >::type( typename std::decay< Args >::type ... )
+ >::type
>
async( Fn && fn, Args && ... args) {
typedef typename std::result_of<
typename std::decay< Fn >::type( typename std::decay< Args >::type ... )
- >::type result_t;
+ >::type result_type;
- packaged_task< result_t( typename std::decay< Args >::type ... ) > pt{
+ packaged_task< result_type( typename std::decay< Args >::type ... ) > pt{
std::forward< Fn >( fn) };
- future< result_t > f{ pt.get_future() };
+ future< result_type > f{ pt.get_future() };
fiber{ std::move( pt), std::forward< Args >( args) ... }.detach();
return f;
}
template< typename Policy, typename Fn, typename ... Args >
future<
- typename std::result_of<
- typename std::enable_if<
- detail::is_launch_policy< Policy >::value,
- typename std::decay< Fn >::type
- >::type( typename std::decay< Args >::type ...)
- >::type
+ typename std::result_of<
+ typename std::enable_if<
+ detail::is_launch_policy< Policy >::value,
+ typename std::decay< Fn >::type
+ >::type( typename std::decay< Args >::type ...)
+ >::type
>
async( Policy policy, Fn && fn, Args && ... args) {
typedef typename std::result_of<
typename std::decay< Fn >::type( typename std::decay< Args >::type ... )
- >::type result_t;
+ >::type result_type;
- packaged_task< result_t( typename std::decay< Args >::type ... ) > pt{
+ packaged_task< result_type( typename std::decay< Args >::type ... ) > pt{
std::forward< Fn >( fn) };
- future< result_t > f{ pt.get_future() };
+ future< result_type > f{ pt.get_future() };
fiber{ policy, std::move( pt), std::forward< Args >( args) ... }.detach();
return f;
}
template< typename Policy, typename StackAllocator, typename Fn, typename ... Args >
future<
- typename std::result_of<
- typename std::enable_if<
- detail::is_launch_policy< Policy >::value,
- typename std::decay< Fn >::type
- >::type( typename std::decay< Args >::type ... )
- >::type
+ typename std::result_of<
+ typename std::enable_if<
+ detail::is_launch_policy< Policy >::value,
+ typename std::decay< Fn >::type
+ >::type( typename std::decay< Args >::type ... )
+ >::type
>
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_t;
+ >::type result_type;
- packaged_task< result_t( typename std::decay< Args >::type ... ) > pt{
- std::allocator_arg, salloc, std::forward< Fn >( fn) };
- future< result_t > f{ pt.get_future() };
+ packaged_task< result_type( typename std::decay< Args >::type ... ) > pt{
+ std::forward< Fn >( fn) };
+ future< result_type > f{ pt.get_future() };
+ fiber{ policy, std::allocator_arg, salloc,
+ std::move( pt), std::forward< Args >( args) ... }.detach();
+ return f;
+}
+
+template< typename Policy, typename StackAllocator, typename Allocator, typename Fn, typename ... Args >
+future<
+ typename std::result_of<
+ typename std::enable_if<
+ detail::is_launch_policy< Policy >::value,
+ typename std::decay< Fn >::type
+ >::type( typename std::decay< Args >::type ... )
+ >::type
+>
+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;
+
+ packaged_task< result_type( typename std::decay< Args >::type ... ) > pt{
+ std::allocator_arg, alloc, std::forward< Fn >( fn) };
+ future< result_type > f{ pt.get_future() };
fiber{ policy, std::allocator_arg, salloc,
std::move( pt), std::forward< Args >( args) ... }.detach();
return f;
diff --git a/boost/fiber/future/detail/shared_state.hpp b/boost/fiber/future/detail/shared_state.hpp
index 5ec6858cf3..898fdaffd4 100644
--- a/boost/fiber/future/detail/shared_state.hpp
+++ b/boost/fiber/future/detail/shared_state.hpp
@@ -109,46 +109,47 @@ public:
shared_state_base & operator=( shared_state_base const&) = delete;
void owner_destroyed() {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
owner_destroyed_( lk);
}
void set_exception( std::exception_ptr except) {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
set_exception_( except, lk);
}
std::exception_ptr get_exception_ptr() {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
return get_exception_ptr_( lk);
}
void wait() const {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
wait_( lk);
}
template< typename Rep, typename Period >
future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
return wait_for_( lk, timeout_duration);
}
template< typename Clock, typename Duration >
future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
return wait_until_( lk, timeout_time);
}
friend inline
void intrusive_ptr_add_ref( shared_state_base * p) noexcept {
- ++p->use_count_;
+ p->use_count_.fetch_add( 1, std::memory_order_relaxed);
}
friend inline
void intrusive_ptr_release( shared_state_base * p) noexcept {
- if ( 0 == --p->use_count_) {
- p->deallocate_future();
+ if ( 1 == p->use_count_.fetch_sub( 1, std::memory_order_release) ) {
+ std::atomic_thread_fence( std::memory_order_acquire);
+ p->deallocate_future();
}
}
};
@@ -161,18 +162,18 @@ private:
void set_value_( R const& value, std::unique_lock< mutex > & lk) {
BOOST_ASSERT( lk.owns_lock() );
if ( ready_) {
- throw promise_already_satisfied();
+ 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_) {
- throw promise_already_satisfied();
+ 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);
}
@@ -186,7 +187,7 @@ private:
}
public:
- typedef intrusive_ptr< shared_state > ptr_t;
+ typedef intrusive_ptr< shared_state > ptr_type;
shared_state() = default;
@@ -200,17 +201,17 @@ public:
shared_state & operator=( shared_state const&) = delete;
void set_value( R const& value) {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
set_value_( value, lk);
}
void set_value( R && value) {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
set_value_( std::move( value), lk);
}
R & get() {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
return get_( lk);
}
};
@@ -239,7 +240,7 @@ private:
}
public:
- typedef intrusive_ptr< shared_state > ptr_t;
+ typedef intrusive_ptr< shared_state > ptr_type;
shared_state() = default;
@@ -249,12 +250,12 @@ public:
shared_state & operator=( shared_state const&) = delete;
void set_value( R & value) {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
set_value_( value, lk);
}
R & get() {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
return get_( lk);
}
};
@@ -281,7 +282,7 @@ private:
}
public:
- typedef intrusive_ptr< shared_state > ptr_t;
+ typedef intrusive_ptr< shared_state > ptr_type;
shared_state() = default;
@@ -292,13 +293,13 @@ public:
inline
void set_value() {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
set_value_( lk);
}
inline
void get() {
- std::unique_lock< mutex > lk( mtx_);
+ std::unique_lock< mutex > lk{ mtx_ };
get_( lk);
}
};
diff --git a/boost/fiber/future/detail/shared_state_object.hpp b/boost/fiber/future/detail/shared_state_object.hpp
index dcdafef65c..50e08a6393 100644
--- a/boost/fiber/future/detail/shared_state_object.hpp
+++ b/boost/fiber/future/detail/shared_state_object.hpp
@@ -27,10 +27,11 @@ class shared_state_object : public shared_state< R > {
public:
typedef typename std::allocator_traits< Allocator >::template rebind_alloc<
shared_state_object
- > allocator_t;
+ > allocator_type;
- shared_state_object( allocator_t const& alloc) :
- shared_state< R >(), alloc_( alloc) {
+ shared_state_object( allocator_type const& alloc) :
+ shared_state< R >{},
+ alloc_{ alloc } {
}
protected:
@@ -39,10 +40,10 @@ protected:
}
private:
- allocator_t alloc_;
+ allocator_type alloc_;
- static void destroy_( allocator_t const& alloc, shared_state_object * p) noexcept {
- allocator_t a{ alloc };
+ static void destroy_( allocator_type const& alloc, shared_state_object * p) noexcept {
+ allocator_type a{ alloc };
a.destroy( p);
a.deallocate( p, 1);
}
diff --git a/boost/fiber/future/detail/task_base.hpp b/boost/fiber/future/detail/task_base.hpp
index 907e820470..83abd7e5ab 100644
--- a/boost/fiber/future/detail/task_base.hpp
+++ b/boost/fiber/future/detail/task_base.hpp
@@ -22,14 +22,14 @@ namespace detail {
template< typename R, typename ... Args >
struct task_base : public shared_state< R > {
- typedef intrusive_ptr< task_base > ptr_t;
+ typedef intrusive_ptr< task_base > ptr_type;
virtual ~task_base() {
}
virtual void run( Args && ... args) = 0;
- virtual ptr_t reset() = 0;
+ virtual ptr_type reset() = 0;
};
}}}
diff --git a/boost/fiber/future/detail/task_object.hpp b/boost/fiber/future/detail/task_object.hpp
index 37bfd3fd11..3a48929a58 100644
--- a/boost/fiber/future/detail/task_object.hpp
+++ b/boost/fiber/future/detail/task_object.hpp
@@ -9,10 +9,13 @@
#include <exception>
#include <memory>
+#include <tuple>
#include <utility>
#include <boost/config.hpp>
+#if defined(BOOST_NO_CXX17_STD_APPLY)
#include <boost/context/detail/apply.hpp>
+#endif
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/future/detail/task_base.hpp>
@@ -28,43 +31,49 @@ namespace detail {
template< typename Fn, typename Allocator, typename R, typename ... Args >
class task_object : public task_base< R, Args ... > {
private:
- typedef task_base< R, Args ... > base_t;
+ typedef task_base< R, Args ... > base_type;
public:
typedef typename std::allocator_traits< Allocator >::template rebind_alloc<
task_object
- > allocator_t;
+ > allocator_type;
- task_object( allocator_t const& alloc, Fn const& fn) :
- base_t(),
- fn_( fn),
- alloc_( alloc) {
+ task_object( allocator_type const& alloc, Fn const& fn) :
+ base_type{},
+ fn_{ fn },
+ alloc_{ alloc } {
}
- task_object( allocator_t const& alloc, Fn && fn) :
- base_t(),
- fn_( std::move( fn) ),
- alloc_( alloc) {
+ task_object( allocator_type const& alloc, Fn && fn) :
+ base_type{},
+ fn_{ std::move( fn) },
+ alloc_{ alloc } {
}
void run( Args && ... args) override final {
try {
this->set_value(
+#if defined(BOOST_NO_CXX17_STD_APPLY)
boost::context::detail::apply(
- fn_, std::make_tuple( std::forward< Args >( args) ... ) ) );
+ fn_, std::make_tuple( std::forward< Args >( args) ... ) )
+#else
+ std::apply(
+ fn_, std::make_tuple( std::forward< Args >( args) ... ) )
+#endif
+ );
} catch (...) {
this->set_exception( std::current_exception() );
}
}
- typename base_t::ptr_t reset() override final {
- typedef std::allocator_traits< allocator_t > traits_t;
+ typename base_type::ptr_type reset() override final {
+ typedef std::allocator_traits< allocator_type > traity_type;
- typename traits_t::pointer ptr{ traits_t::allocate( alloc_, 1) };
+ typename traity_type::pointer ptr{ traity_type::allocate( alloc_, 1) };
try {
- traits_t::construct( alloc_, ptr, alloc_, std::move( fn_) );
+ traity_type::construct( alloc_, ptr, alloc_, std::move( fn_) );
} catch (...) {
- traits_t::deallocate( alloc_, ptr, 1);
+ traity_type::deallocate( alloc_, ptr, 1);
throw;
}
return { convert( ptr) };
@@ -77,10 +86,10 @@ protected:
private:
Fn fn_;
- allocator_t alloc_;
+ allocator_type alloc_;
- static void destroy_( allocator_t const& alloc, task_object * p) noexcept {
- allocator_t a{ alloc };
+ static void destroy_( allocator_type const& alloc, task_object * p) noexcept {
+ allocator_type a{ alloc };
a.destroy( p);
a.deallocate( p, 1);
}
@@ -89,43 +98,48 @@ private:
template< typename Fn, typename Allocator, typename ... Args >
class task_object< Fn, Allocator, void, Args ... > : public task_base< void, Args ... > {
private:
- typedef task_base< void, Args ... > base_t;
+ typedef task_base< void, Args ... > base_type;
public:
typedef typename Allocator::template rebind<
task_object< Fn, Allocator, void, Args ... >
- >::other allocator_t;
+ >::other allocator_type;
- task_object( allocator_t const& alloc, Fn const& fn) :
- base_t(),
- fn_( fn),
- alloc_( alloc) {
+ task_object( allocator_type const& alloc, Fn const& fn) :
+ base_type{},
+ fn_{ fn },
+ alloc_{ alloc } {
}
- task_object( allocator_t const& alloc, Fn && fn) :
- base_t(),
- fn_( std::move( fn) ),
- alloc_( alloc) {
+ task_object( allocator_type const& alloc, Fn && fn) :
+ base_type{},
+ fn_{ std::move( fn) },
+ alloc_{ alloc } {
}
void run( Args && ... args) override final {
try {
+#if defined(BOOST_NO_CXX17_STD_APPLY)
boost::context::detail::apply(
fn_, std::make_tuple( std::forward< Args >( args) ... ) );
+#else
+ std::apply(
+ fn_, std::make_tuple( std::forward< Args >( args) ... ) );
+#endif
this->set_value();
} catch (...) {
this->set_exception( std::current_exception() );
}
}
- typename base_t::ptr_t reset() override final {
- typedef std::allocator_traits< allocator_t > traits_t;
+ typename base_type::ptr_type reset() override final {
+ typedef std::allocator_traits< allocator_type > traity_type;
- typename traits_t::pointer ptr{ traits_t::allocate( alloc_, 1) };
+ typename traity_type::pointer ptr{ traity_type::allocate( alloc_, 1) };
try {
- traits_t::construct( alloc_, ptr, alloc_, std::move( fn_) );
+ traity_type::construct( alloc_, ptr, alloc_, std::move( fn_) );
} catch (...) {
- traits_t::deallocate( alloc_, ptr, 1);
+ traity_type::deallocate( alloc_, ptr, 1);
throw;
}
return { convert( ptr) };
@@ -138,10 +152,10 @@ protected:
private:
Fn fn_;
- allocator_t alloc_;
+ allocator_type alloc_;
- static void destroy_( allocator_t const& alloc, task_object * p) noexcept {
- allocator_t a{ alloc };
+ static void destroy_( allocator_type const& alloc, task_object * p) noexcept {
+ allocator_type a{ alloc };
a.destroy( p);
a.deallocate( p, 1);
}
diff --git a/boost/fiber/future/future.hpp b/boost/fiber/future/future.hpp
index d92820eb58..5d4ad78ab5 100644
--- a/boost/fiber/future/future.hpp
+++ b/boost/fiber/future/future.hpp
@@ -24,13 +24,13 @@ namespace detail {
template< typename R >
struct future_base {
- typedef typename shared_state< R >::ptr_t ptr_t;
+ typedef typename shared_state< R >::ptr_type ptr_type;
- ptr_t state_{};
+ ptr_type state_{};
- future_base() noexcept = default;
+ future_base() = default;
- explicit future_base( ptr_t const& p) noexcept :
+ explicit future_base( ptr_type const& p) noexcept :
state_{ p } {
}
@@ -46,15 +46,17 @@ struct future_base {
}
future_base & operator=( future_base const& other) noexcept {
- if ( this == & other) return * this;
- state_ = other.state_;
+ if ( this != & other) {
+ state_ = other.state_;
+ }
return * this;
}
future_base & operator=( future_base && other) noexcept {
- if ( this == & other) return * this;
- state_ = other.state_;
- other.state_.reset();
+ if ( this != & other) {
+ state_ = other.state_;
+ other.state_.reset();
+ }
return * this;
}
@@ -107,128 +109,131 @@ class packaged_task;
template< typename R >
class future : private detail::future_base< R > {
private:
- typedef detail::future_base< R > base_t;
+ typedef detail::future_base< R > base_type;
friend struct detail::promise_base< R >;
friend class shared_future< R >;
template< typename Signature >
friend class packaged_task;
- explicit future( typename base_t::ptr_t const& p) noexcept :
- base_t{ p } {
+ explicit future( typename base_type::ptr_type const& p) noexcept :
+ base_type{ p } {
}
public:
- future() noexcept = default;
+ future() = default;
future( future const&) = delete;
future & operator=( future const&) = delete;
future( future && other) noexcept :
- base_t{ std::move( other) } {
+ base_type{ std::move( other) } {
}
future & operator=( future && other) noexcept {
- if ( this == & other) return * this;
- base_t::operator=( std::move( other) );
+ if ( this != & other) {
+ base_type::operator=( std::move( other) );
+ }
return * this;
}
shared_future< R > share();
R get() {
- if ( ! base_t::valid() ) {
+ if ( ! base_type::valid() ) {
throw future_uninitialized{};
}
- typename base_t::ptr_t tmp{};
- tmp.swap( base_t::state_);
+ typename base_type::ptr_type tmp{};
+ tmp.swap( base_type::state_);
return std::move( tmp->get() );
}
- using base_t::valid;
- using base_t::get_exception_ptr;
- using base_t::wait;
- using base_t::wait_for;
- using base_t::wait_until;
+ using base_type::valid;
+ using base_type::get_exception_ptr;
+ using base_type::wait;
+ using base_type::wait_for;
+ using base_type::wait_until;
};
template< typename R >
class future< R & > : private detail::future_base< R & > {
private:
- typedef detail::future_base< R & > base_t;
+ typedef detail::future_base< R & > base_type;
friend struct detail::promise_base< R & >;
friend class shared_future< R & >;
template< typename Signature >
friend class packaged_task;
- explicit future( typename base_t::ptr_t const& p) noexcept :
- base_t{ p } {
+ explicit future( typename base_type::ptr_type const& p) noexcept :
+ base_type{ p } {
}
public:
- future() noexcept = default;
+ future() = default;
future( future const&) = delete;
future & operator=( future const&) = delete;
future( future && other) noexcept :
- base_t{ std::move( other) } {
+ base_type{ std::move( other) } {
}
future & operator=( future && other) noexcept {
- if ( this == & other) return * this;
- base_t::operator=( std::move( other) );
+ if ( this != & other) {
+ base_type::operator=( std::move( other) );
+ }
return * this;
}
shared_future< R & > share();
R & get() {
- if ( ! base_t::valid() ) {
+ if ( ! base_type::valid() ) {
throw future_uninitialized{};
}
- typename base_t::ptr_t tmp{};
- tmp.swap( base_t::state_);
+ typename base_type::ptr_type tmp{};
+ tmp.swap( base_type::state_);
return tmp->get();
}
- using base_t::valid;
- using base_t::get_exception_ptr;
- using base_t::wait;
- using base_t::wait_for;
- using base_t::wait_until;
+ using base_type::valid;
+ using base_type::get_exception_ptr;
+ using base_type::wait;
+ using base_type::wait_for;
+ using base_type::wait_until;
};
template<>
class future< void > : private detail::future_base< void > {
private:
- typedef detail::future_base< void > base_t;
+ typedef detail::future_base< void > base_type;
friend struct detail::promise_base< void >;
friend class shared_future< void >;
template< typename Signature >
friend class packaged_task;
- explicit future( base_t::ptr_t const& p) noexcept :
- base_t{ p } {
+ explicit future( base_type::ptr_type const& p) noexcept :
+ base_type{ p } {
}
public:
- future() noexcept = default;
+ future() = default;
future( future const&) = delete;
future & operator=( future const&) = delete;
inline
future( future && other) noexcept :
- base_t{ std::move( other) } {
+ base_type{ std::move( other) } {
}
inline
future & operator=( future && other) noexcept {
- if ( this == & other) return * this;
- base_t::operator=( std::move( other) );
+ if ( this != & other) {
+ base_type::operator=( std::move( other) );
+ }
return * this;
}
@@ -236,62 +241,64 @@ public:
inline
void get() {
- if ( ! base_t::valid() ) {
+ if ( ! base_type::valid() ) {
throw future_uninitialized{};
}
- base_t::ptr_t tmp{};
- tmp.swap( base_t::state_);
+ base_type::ptr_type tmp{};
+ tmp.swap( base_type::state_);
tmp->get();
}
- using base_t::valid;
- using base_t::get_exception_ptr;
- using base_t::wait;
- using base_t::wait_for;
- using base_t::wait_until;
+ using base_type::valid;
+ using base_type::get_exception_ptr;
+ using base_type::wait;
+ using base_type::wait_for;
+ using base_type::wait_until;
};
template< typename R >
class shared_future : private detail::future_base< R > {
private:
- typedef detail::future_base< R > base_t;
+ typedef detail::future_base< R > base_type;
- explicit shared_future( typename base_t::ptr_t const& p) noexcept :
- base_t{ p } {
+ explicit shared_future( typename base_type::ptr_type const& p) noexcept :
+ base_type{ p } {
}
public:
- shared_future() noexcept = default;
+ shared_future() = default;
~shared_future() = default;
shared_future( shared_future const& other) :
- base_t{ other } {
+ base_type{ other } {
}
shared_future( shared_future && other) noexcept :
- base_t{ std::move( other) } {
+ base_type{ std::move( other) } {
}
shared_future( future< R > && other) noexcept :
- base_t{ std::move( other) } {
+ base_type{ std::move( other) } {
}
shared_future & operator=( shared_future const& other) noexcept {
- if ( this == & other) return * this;
- base_t::operator=( other);
+ if ( this != & other) {
+ base_type::operator=( other);
+ }
return * this;
}
shared_future & operator=( shared_future && other) noexcept {
- if ( this == & other) return * this;
- base_t::operator=( std::move( other) );
+ if ( this != & other) {
+ base_type::operator=( std::move( other) );
+ }
return * this;
}
shared_future & operator=( future< R > && other) noexcept {
- base_t::operator=( std::move( other) );
+ base_type::operator=( std::move( other) );
return * this;
}
@@ -299,56 +306,58 @@ public:
if ( ! valid() ) {
throw future_uninitialized{};
}
- return base_t::state_->get();
+ return base_type::state_->get();
}
- using base_t::valid;
- using base_t::get_exception_ptr;
- using base_t::wait;
- using base_t::wait_for;
- using base_t::wait_until;
+ using base_type::valid;
+ using base_type::get_exception_ptr;
+ using base_type::wait;
+ using base_type::wait_for;
+ using base_type::wait_until;
};
template< typename R >
class shared_future< R & > : private detail::future_base< R & > {
private:
- typedef detail::future_base< R & > base_t;
+ typedef detail::future_base< R & > base_type;
- explicit shared_future( typename base_t::ptr_t const& p) noexcept :
- base_t{ p } {
+ explicit shared_future( typename base_type::ptr_type const& p) noexcept :
+ base_type{ p } {
}
public:
- shared_future() noexcept = default;
+ shared_future() = default;
~shared_future() = default;
shared_future( shared_future const& other) :
- base_t{ other } {
+ base_type{ other } {
}
shared_future( shared_future && other) noexcept :
- base_t{ std::move( other) } {
+ base_type{ std::move( other) } {
}
shared_future( future< R & > && other) noexcept :
- base_t{ std::move( other) } {
+ base_type{ std::move( other) } {
}
shared_future & operator=( shared_future const& other) noexcept {
- if ( this == & other) return * this;
- base_t::operator=( other);
+ if ( this != & other) {
+ base_type::operator=( other);
+ }
return * this;
}
shared_future & operator=( shared_future && other) noexcept {
- if ( this == & other) return * this;
- base_t::operator=( std::move( other) );
+ if ( this != & other) {
+ base_type::operator=( std::move( other) );
+ }
return * this;
}
shared_future & operator=( future< R & > && other) noexcept {
- base_t::operator=( std::move( other) );
+ base_type::operator=( std::move( other) );
return * this;
}
@@ -356,62 +365,64 @@ public:
if ( ! valid() ) {
throw future_uninitialized{};
}
- return base_t::state_->get();
+ return base_type::state_->get();
}
- using base_t::valid;
- using base_t::get_exception_ptr;
- using base_t::wait;
- using base_t::wait_for;
- using base_t::wait_until;
+ using base_type::valid;
+ using base_type::get_exception_ptr;
+ using base_type::wait;
+ using base_type::wait_for;
+ using base_type::wait_until;
};
template<>
class shared_future< void > : private detail::future_base< void > {
private:
- typedef detail::future_base< void > base_t;
+ typedef detail::future_base< void > base_type;
- explicit shared_future( base_t::ptr_t const& p) noexcept :
- base_t{ p } {
+ explicit shared_future( base_type::ptr_type const& p) noexcept :
+ base_type{ p } {
}
public:
- shared_future() noexcept = default;
+ shared_future() = default;
~shared_future() = default;
inline
shared_future( shared_future const& other) :
- base_t{ other } {
+ base_type{ other } {
}
inline
shared_future( shared_future && other) noexcept :
- base_t{ std::move( other) } {
+ base_type{ std::move( other) } {
}
inline
shared_future( future< void > && other) noexcept :
- base_t{ std::move( other) } {
+ base_type{ std::move( other) } {
}
inline
shared_future & operator=( shared_future const& other) noexcept {
- if ( this == & other) return * this;
- base_t::operator=( other);
+ if ( this != & other) {
+ base_type::operator=( other);
+ }
return * this;
}
inline
shared_future & operator=( shared_future && other) noexcept {
- if ( this == & other) return * this;
- base_t::operator=( std::move( other) );
+ if ( this != & other) {
+ base_type::operator=( std::move( other) );
+ }
return * this;
}
inline
shared_future & operator=( future< void > && other) noexcept {
- base_t::operator=( std::move( other) );
+ base_type::operator=( std::move( other) );
return * this;
}
@@ -420,21 +431,21 @@ public:
if ( ! valid() ) {
throw future_uninitialized{};
}
- base_t::state_->get();
+ base_type::state_->get();
}
- using base_t::valid;
- using base_t::get_exception_ptr;
- using base_t::wait;
- using base_t::wait_for;
- using base_t::wait_until;
+ using base_type::valid;
+ using base_type::get_exception_ptr;
+ using base_type::wait;
+ using base_type::wait_for;
+ using base_type::wait_until;
};
template< typename R >
shared_future< R >
future< R >::share() {
- if ( ! base_t::valid() ) {
+ if ( ! base_type::valid() ) {
throw future_uninitialized{};
}
return shared_future< R >{ std::move( * this) };
@@ -443,7 +454,7 @@ future< R >::share() {
template< typename R >
shared_future< R & >
future< R & >::share() {
- if ( ! base_t::valid() ) {
+ if ( ! base_type::valid() ) {
throw future_uninitialized{};
}
return shared_future< R & >{ std::move( * this) };
@@ -452,7 +463,7 @@ future< R & >::share() {
inline
shared_future< void >
future< void >::share() {
- if ( ! base_t::valid() ) {
+ if ( ! 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 7ea16bfee7..31838ee41f 100644
--- a/boost/fiber/future/packaged_task.hpp
+++ b/boost/fiber/future/packaged_task.hpp
@@ -30,13 +30,13 @@ class packaged_task;
template< typename R, typename ... Args >
class packaged_task< R( Args ... ) > {
private:
- typedef typename detail::task_base< R, Args ... >::ptr_t ptr_t;
+ typedef typename detail::task_base< R, Args ... >::ptr_type ptr_type;
bool obtained_{ false };
- ptr_t task_{};
+ ptr_type task_{};
public:
- constexpr packaged_task() noexcept = default;
+ packaged_task() = default;
template< typename Fn,
typename = detail::disable_overload< packaged_task, Fn >
@@ -53,17 +53,17 @@ public:
explicit packaged_task( std::allocator_arg_t, Allocator const& alloc, Fn && fn) {
typedef detail::task_object<
typename std::decay< Fn >::type, Allocator, R, Args ...
- > object_t;
+ > object_type;
typedef std::allocator_traits<
- typename object_t::allocator_t
- > traits_t;
+ typename object_type::allocator_type
+ > traits_type;
- typename object_t::allocator_t a{ alloc };
- typename traits_t::pointer ptr{ traits_t::allocate( a, 1) };
+ typename object_type::allocator_type a{ alloc };
+ typename traits_type::pointer ptr{ traits_type::allocate( a, 1) };
try {
- traits_t::construct( a, ptr, a, std::forward< Fn >( fn) );
+ traits_type::construct( a, ptr, a, std::forward< Fn >( fn) );
} catch (...) {
- traits_t::deallocate( a, ptr, 1);
+ traits_type::deallocate( a, ptr, 1);
throw;
}
task_.reset( convert( ptr) );
@@ -85,9 +85,10 @@ public:
}
packaged_task & operator=( packaged_task && other) noexcept {
- if ( this == & other) return * this;
- packaged_task tmp{ std::move( other) };
- swap( tmp);
+ if ( this != & other) {
+ packaged_task tmp{ std::move( other) };
+ swap( tmp);
+ }
return * this;
}
diff --git a/boost/fiber/future/promise.hpp b/boost/fiber/future/promise.hpp
index 278c839700..83ba63fb23 100644
--- a/boost/fiber/future/promise.hpp
+++ b/boost/fiber/future/promise.hpp
@@ -25,10 +25,10 @@ namespace detail {
template< typename R >
struct promise_base {
- typedef typename shared_state< R >::ptr_t ptr_t;
+ typedef typename shared_state< R >::ptr_type ptr_type;
bool obtained_{ false };
- ptr_t future_{};
+ ptr_type future_{};
promise_base() :
promise_base{ std::allocator_arg, std::allocator< promise_base >{} } {
@@ -36,15 +36,15 @@ struct promise_base {
template< typename Allocator >
promise_base( std::allocator_arg_t, Allocator alloc) {
- typedef detail::shared_state_object< R, Allocator > object_t;
- typedef std::allocator_traits< typename object_t::allocator_t > traits_t;
- typename object_t::allocator_t a{ alloc };
- typename traits_t::pointer ptr{ traits_t::allocate( a, 1) };
+ typedef detail::shared_state_object< R, Allocator > object_type;
+ typedef std::allocator_traits< typename object_type::allocator_type > traits_type;
+ typename object_type::allocator_type a{ alloc };
+ typename traits_type::pointer ptr{ traits_type::allocate( a, 1) };
try {
- traits_t::construct( a, ptr, a);
+ traits_type::construct( a, ptr, a);
} catch (...) {
- traits_t::deallocate( a, ptr, 1);
+ traits_type::deallocate( a, ptr, 1);
throw;
}
future_.reset( convert( ptr) );
@@ -66,9 +66,10 @@ struct promise_base {
}
promise_base & operator=( promise_base && other) noexcept {
- if ( this == & other) return * this;
- promise_base tmp{ std::move( other) };
- swap( tmp);
+ if ( this != & other) {
+ promise_base tmp{ std::move( other) };
+ swap( tmp);
+ }
return * this;
}
@@ -101,14 +102,14 @@ struct promise_base {
template< typename R >
class promise : private detail::promise_base< R > {
private:
- typedef detail::promise_base< R > base_t;
+ typedef detail::promise_base< R > base_type;
public:
promise() = default;
template< typename Allocator >
promise( std::allocator_arg_t, Allocator alloc) :
- base_t{ std::allocator_arg, alloc } {
+ base_type{ std::allocator_arg, alloc } {
}
promise( promise const&) = delete;
@@ -118,38 +119,38 @@ public:
promise & operator=( promise && other) = default;
void set_value( R const& value) {
- if ( ! base_t::future_) {
+ if ( ! base_type::future_) {
throw promise_uninitialized{};
}
- base_t::future_->set_value( value);
+ base_type::future_->set_value( value);
}
void set_value( R && value) {
- if ( ! base_t::future_) {
+ if ( ! base_type::future_) {
throw promise_uninitialized{};
}
- base_t::future_->set_value( std::move( value) );
+ base_type::future_->set_value( std::move( value) );
}
void swap( promise & other) noexcept {
- base_t::swap( other);
+ base_type::swap( other);
}
- using base_t::get_future;
- using base_t::set_exception;
+ using base_type::get_future;
+ using base_type::set_exception;
};
template< typename R >
class promise< R & > : private detail::promise_base< R & > {
private:
- typedef detail::promise_base< R & > base_t;
+ typedef detail::promise_base< R & > base_type;
public:
promise() = default;
template< typename Allocator >
promise( std::allocator_arg_t, Allocator alloc) :
- base_t{ std::allocator_arg, alloc } {
+ base_type{ std::allocator_arg, alloc } {
}
promise( promise const&) = delete;
@@ -159,31 +160,31 @@ public:
promise & operator=( promise && other) noexcept = default;
void set_value( R & value) {
- if ( ! base_t::future_) {
+ if ( ! base_type::future_) {
throw promise_uninitialized{};
}
- base_t::future_->set_value( value);
+ base_type::future_->set_value( value);
}
void swap( promise & other) noexcept {
- base_t::swap( other);
+ base_type::swap( other);
}
- using base_t::get_future;
- using base_t::set_exception;
+ using base_type::get_future;
+ using base_type::set_exception;
};
template<>
class promise< void > : private detail::promise_base< void > {
private:
- typedef detail::promise_base< void > base_t;
+ typedef detail::promise_base< void > base_type;
public:
promise() = default;
template< typename Allocator >
promise( std::allocator_arg_t, Allocator alloc) :
- base_t{ std::allocator_arg, alloc } {
+ base_type{ std::allocator_arg, alloc } {
}
promise( promise const&) = delete;
@@ -194,19 +195,19 @@ public:
inline
void set_value() {
- if ( ! base_t::future_) {
+ if ( ! base_type::future_) {
throw promise_uninitialized{};
}
- base_t::future_->set_value();
+ base_type::future_->set_value();
}
inline
void swap( promise & other) noexcept {
- base_t::swap( other);
+ base_type::swap( other);
}
- using base_t::get_future;
- using base_t::set_exception;
+ using base_type::get_future;
+ using base_type::set_exception;
};
template< typename R >
diff --git a/boost/fiber/mutex.hpp b/boost/fiber/mutex.hpp
index b56e96802a..e25ef04d9e 100644
--- a/boost/fiber/mutex.hpp
+++ b/boost/fiber/mutex.hpp
@@ -33,11 +33,11 @@ class BOOST_FIBERS_DECL mutex {
private:
friend class condition_variable;
- typedef context::wait_queue_t wait_queue_t;
+ typedef context::wait_queue_t wait_queue_type;
- context * owner_{ nullptr };
- wait_queue_t wait_queue_{};
detail::spinlock wait_queue_splk_{};
+ wait_queue_type wait_queue_{};
+ context * owner_{ nullptr };
public:
mutex() = default;
diff --git a/boost/fiber/operations.hpp b/boost/fiber/operations.hpp
index 490ba462f6..95ab9ba452 100644
--- a/boost/fiber/operations.hpp
+++ b/boost/fiber/operations.hpp
@@ -35,8 +35,7 @@ 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_) );
+ std::chrono::steady_clock::time_point sleep_time = boost::fibers::detail::convert( sleep_time_);
fibers::context::active()->wait_until( sleep_time);
}
@@ -48,8 +47,7 @@ void sleep_for( std::chrono::duration< Rep, Period > const& timeout_duration) {
template< typename PROPS >
PROPS & properties() {
- fibers::fiber_properties * props =
- fibers::context::active()->get_properties();
+ fibers::fiber_properties * props = fibers::context::active()->get_properties();
if ( ! props) {
// props could be nullptr if the thread's main fiber has not yet
// yielded (not yet passed through algorithm_with_properties::
@@ -61,7 +59,7 @@ PROPS & properties() {
props = fibers::context::active()->get_properties();
// Could still be hosed if the running manager isn't a subclass of
// algorithm_with_properties.
- BOOST_ASSERT_MSG(props, "this_fiber::properties not set");
+ BOOST_ASSERT_MSG( props, "this_fiber::properties not set");
}
return dynamic_cast< PROPS & >( * props );
}
diff --git a/boost/fiber/recursive_mutex.hpp b/boost/fiber/recursive_mutex.hpp
index 66fb5aa7c3..864c65cb8e 100644
--- a/boost/fiber/recursive_mutex.hpp
+++ b/boost/fiber/recursive_mutex.hpp
@@ -37,12 +37,12 @@ class BOOST_FIBERS_DECL recursive_mutex {
private:
friend class condition_variable;
- typedef context::wait_queue_t wait_queue_t;
+ typedef context::wait_queue_t wait_queue_type;
+ detail::spinlock wait_queue_splk_{};
+ wait_queue_type wait_queue_{};
context * owner_{ nullptr };
std::size_t count_{ 0 };
- wait_queue_t wait_queue_{};
- detail::spinlock wait_queue_splk_{};
public:
recursive_mutex() = default;
diff --git a/boost/fiber/recursive_timed_mutex.hpp b/boost/fiber/recursive_timed_mutex.hpp
index 2852252cd0..339427b895 100644
--- a/boost/fiber/recursive_timed_mutex.hpp
+++ b/boost/fiber/recursive_timed_mutex.hpp
@@ -39,12 +39,12 @@ class BOOST_FIBERS_DECL recursive_timed_mutex {
private:
friend class condition_variable;
- typedef context::wait_queue_t wait_queue_t;
+ typedef context::wait_queue_t wait_queue_type;
+ detail::spinlock wait_queue_splk_{};
+ wait_queue_type wait_queue_{};
context * owner_{ nullptr };
std::size_t count_{ 0 };
- wait_queue_t wait_queue_{};
- detail::spinlock wait_queue_splk_{};
bool try_lock_until_( std::chrono::steady_clock::time_point const& timeout_time) noexcept;
@@ -66,8 +66,7 @@ public:
template< typename Clock, typename Duration >
bool try_lock_until( std::chrono::time_point< Clock, Duration > const& timeout_time_) {
- std::chrono::steady_clock::time_point timeout_time(
- detail::convert( timeout_time_) );
+ std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
return try_lock_until_( timeout_time);
}
diff --git a/boost/fiber/scheduler.hpp b/boost/fiber/scheduler.hpp
index 4503bc0b5f..4a5f0dab8c 100644
--- a/boost/fiber/scheduler.hpp
+++ b/boost/fiber/scheduler.hpp
@@ -13,15 +13,19 @@
#include <vector>
#include <boost/config.hpp>
-#include <boost/context/execution_context.hpp>
+#if (BOOST_EXECUTION_CONTEXT==1)
+# include <boost/context/execution_context.hpp>
+#else
+# include <boost/context/continuation.hpp>
+#endif
#include <boost/intrusive/list.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/intrusive/set.hpp>
+#include <boost/intrusive/slist.hpp>
#include <boost/fiber/algo/algorithm.hpp>
#include <boost/fiber/context.hpp>
#include <boost/fiber/detail/config.hpp>
-#include <boost/fiber/detail/context_mpsc_queue.hpp>
#include <boost/fiber/detail/data.hpp>
#include <boost/fiber/detail/spinlock.hpp>
@@ -49,45 +53,56 @@ public:
context,
intrusive::member_hook<
context, detail::ready_hook, & context::ready_hook_ >,
- intrusive::constant_time_size< false > > ready_queue_t;
+ intrusive::constant_time_size< false >
+ > ready_queue_type;
private:
typedef intrusive::multiset<
context,
intrusive::member_hook<
context, detail::sleep_hook, & context::sleep_hook_ >,
intrusive::constant_time_size< false >,
- intrusive::compare< timepoint_less > > sleep_queue_t;
+ intrusive::compare< timepoint_less >
+ > sleep_queue_type;
typedef intrusive::list<
context,
intrusive::member_hook<
+ context, detail::worker_hook, & context::worker_hook_ >,
+ intrusive::constant_time_size< false >
+ > worker_queue_type;
+ typedef intrusive::slist<
+ context,
+ intrusive::member_hook<
context, detail::terminated_hook, & context::terminated_hook_ >,
- intrusive::constant_time_size< false > > terminated_queue_t;
- typedef intrusive::list<
+ intrusive::linear< true >,
+ intrusive::cache_last< true >
+ > terminated_queue_type;
+ typedef intrusive::slist<
context,
intrusive::member_hook<
- context, detail::worker_hook, & context::worker_hook_ >,
- intrusive::constant_time_size< false > > worker_queue_t;
+ context, detail::remote_ready_hook, & context::remote_ready_hook_ >,
+ intrusive::linear< true >,
+ intrusive::cache_last< true >
+ > remote_ready_queue_type;
- std::unique_ptr< algo::algorithm > algo_;
- context * main_ctx_{ nullptr };
- intrusive_ptr< context > dispatcher_ctx_{};
- // worker-queue contains all context' mananged by this scheduler
- // except main-context and dispatcher-context
- // unlink happens on destruction of a context
- worker_queue_t worker_queue_{};
- // terminated-queue contains context' which have been terminated
- terminated_queue_t terminated_queue_{};
#if ! defined(BOOST_FIBERS_NO_ATOMICS)
// remote ready-queue contains context' signaled by schedulers
// running in other threads
- detail::context_mpsc_queue remote_ready_queue_{};
- // sleep-queue contains context' which have been called
+ detail::spinlock remote_ready_splk_{};
+ remote_ready_queue_type remote_ready_queue_{};
#endif
+ alignas(cache_alignment) std::unique_ptr< algo::algorithm > algo_;
+ // sleep-queue contains context' which have been called
// scheduler::wait_until()
- sleep_queue_t sleep_queue_{};
- bool shutdown_{ false };
-
- context * get_next_() noexcept;
+ sleep_queue_type sleep_queue_{};
+ // worker-queue contains all context' mananged by this scheduler
+ // except main-context and dispatcher-context
+ // unlink happens on destruction of a context
+ worker_queue_type worker_queue_{};
+ // terminated-queue contains context' which have been terminated
+ terminated_queue_type terminated_queue_{};
+ intrusive_ptr< context > dispatcher_ctx_{};
+ context * main_ctx_{ nullptr };
+ bool shutdown_{ false };
void release_terminated_() noexcept;
@@ -105,20 +120,20 @@ public:
virtual ~scheduler();
- void set_ready( context *) noexcept;
+ void schedule( context *) noexcept;
#if ! defined(BOOST_FIBERS_NO_ATOMICS)
- void set_remote_ready( context *) noexcept;
+ void schedule_from_remote( context *) noexcept;
#endif
#if (BOOST_EXECUTION_CONTEXT==1)
void dispatch() noexcept;
- void set_terminated( context *) noexcept;
+ void terminate( detail::spinlock_lock &, context *) noexcept;
#else
- boost::context::execution_context< detail::data_t * > dispatch() noexcept;
+ boost::context::continuation dispatch() noexcept;
- boost::context::execution_context< detail::data_t * > set_terminated( context *) noexcept;
+ boost::context::continuation terminate( detail::spinlock_lock &, context *) noexcept;
#endif
void yield( context *) noexcept;
diff --git a/boost/fiber/timed_mutex.hpp b/boost/fiber/timed_mutex.hpp
index ed6dbd458e..f74c5e41ad 100644
--- a/boost/fiber/timed_mutex.hpp
+++ b/boost/fiber/timed_mutex.hpp
@@ -35,11 +35,11 @@ class BOOST_FIBERS_DECL timed_mutex {
private:
friend class condition_variable;
- typedef context::wait_queue_t wait_queue_t;
+ typedef context::wait_queue_t wait_queue_type;
- context * owner_{ nullptr };
- wait_queue_t wait_queue_{};
detail::spinlock wait_queue_splk_{};
+ wait_queue_type wait_queue_{};
+ context * owner_{ nullptr };
bool try_lock_until_( std::chrono::steady_clock::time_point const& timeout_time) noexcept;
@@ -60,8 +60,7 @@ public:
template< typename Clock, typename Duration >
bool try_lock_until( std::chrono::time_point< Clock, Duration > const& timeout_time_) {
- std::chrono::steady_clock::time_point timeout_time(
- detail::convert( timeout_time_) );
+ std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
return try_lock_until_( timeout_time);
}
diff --git a/boost/fiber/type.hpp b/boost/fiber/type.hpp
index 9346265856..065d22fccb 100644
--- a/boost/fiber/type.hpp
+++ b/boost/fiber/type.hpp
@@ -18,7 +18,6 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/detail/apply.hpp>
-#include <boost/context/execution_context.hpp>
#include <boost/context/stack_context.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/parent_from_member.hpp>
diff --git a/boost/fiber/unbounded_channel.hpp b/boost/fiber/unbounded_channel.hpp
deleted file mode 100644
index 6de5a6f5f0..0000000000
--- a/boost/fiber/unbounded_channel.hpp
+++ /dev/null
@@ -1,272 +0,0 @@
-
-// Copyright Oliver Kowalke 2013.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_FIBERS_UNBOUNDED_CHANNEL_H
-#define BOOST_FIBERS_UNBOUNDED_CHANNEL_H
-
-#warn "template unbounded_channel is deprecated"
-
-#include <atomic>
-#include <algorithm>
-#include <chrono>
-#include <cstddef>
-#include <deque>
-#include <memory>
-#include <mutex>
-#include <utility>
-
-#include <boost/config.hpp>
-#include <boost/intrusive_ptr.hpp>
-
-#include <boost/fiber/detail/config.hpp>
-#include <boost/fiber/channel_op_status.hpp>
-#include <boost/fiber/condition_variable.hpp>
-#include <boost/fiber/detail/convert.hpp>
-#include <boost/fiber/exceptions.hpp>
-#include <boost/fiber/mutex.hpp>
-#include <boost/fiber/operations.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace fibers {
-
-template< typename T,
- typename Allocator = std::allocator< T >
->
-class unbounded_channel {
-public:
- typedef T value_type;
-
-private:
- struct node {
- typedef intrusive_ptr< node > ptr_t;
- typedef typename std::allocator_traits< Allocator >::template rebind_alloc<
- node
- > allocator_t;
- typedef std::allocator_traits< allocator_t > allocator_traits_t;
-
-#if ! defined(BOOST_FIBERS_NO_ATOMICS)
- std::atomic< std::size_t > use_count{ 0 };
-#else
- std::size_t use_count{ 0 };
-#endif
- allocator_t alloc;
- T va;
- ptr_t nxt{};
-
- node( T const& t, allocator_t const& alloc_) noexcept :
- alloc{ alloc_ },
- va{ t } {
- }
-
- node( T && t, allocator_t const& alloc_) noexcept :
- alloc{ alloc_ },
- va{ std::move( t) } {
- }
-
- friend
- void intrusive_ptr_add_ref( node * p) noexcept {
- ++p->use_count;
- }
-
- friend
- void intrusive_ptr_release( node * p) noexcept {
- if ( 0 == --p->use_count) {
- allocator_t alloc( p->alloc);
- allocator_traits_t::destroy( alloc, p);
- allocator_traits_t::deallocate( alloc, p, 1);
- }
- }
- };
-
- using ptr_t = typename node::ptr_t;
- using allocator_t = typename node::allocator_t;
- using allocator_traits_t = typename node::allocator_traits_t;
-
- enum class queue_status {
- open = 0,
- closed
- };
-
- allocator_t alloc_;
- queue_status state_{ queue_status::open };
- ptr_t head_{};
- ptr_t * tail_;
- mutable mutex mtx_{};
- condition_variable not_empty_cond_{};
-
- bool is_closed_() const noexcept {
- return queue_status::closed == state_;
- }
-
- void close_( std::unique_lock< mutex > & lk) noexcept {
- state_ = queue_status::closed;
- lk.unlock();
- not_empty_cond_.notify_all();
- }
-
- bool is_empty_() const noexcept {
- return ! head_;
- }
-
- channel_op_status push_( ptr_t new_node,
- std::unique_lock< mutex > & lk) noexcept {
- if ( is_closed_() ) {
- return channel_op_status::closed;
- }
- return push_and_notify_( new_node, lk);
- }
-
- channel_op_status push_and_notify_( ptr_t new_node,
- std::unique_lock< mutex > & lk) noexcept {
- push_tail_( new_node);
- lk.unlock();
- not_empty_cond_.notify_one();
- return channel_op_status::success;
- }
-
- void push_tail_( ptr_t new_node) noexcept {
- * tail_ = new_node;
- tail_ = & new_node->nxt;
- }
-
- value_type value_pop_( std::unique_lock< mutex > & lk) {
- BOOST_ASSERT( ! is_empty_() );
- auto old_head = pop_head_();
- return std::move( old_head->va);
- }
-
- ptr_t pop_head_() noexcept {
- auto old_head = head_;
- head_ = old_head->nxt;
- if ( ! head_) {
- tail_ = & head_;
- }
- old_head->nxt.reset();
- return old_head;
- }
-
-public:
- explicit unbounded_channel( Allocator const& alloc = Allocator() ) noexcept :
- alloc_{ alloc },
- tail_{ & head_ } {
- }
-
- unbounded_channel( unbounded_channel const&) = delete;
- unbounded_channel & operator=( unbounded_channel const&) = delete;
-
- void close() noexcept {
- std::unique_lock< mutex > lk( mtx_);
- close_( lk);
- }
-
- channel_op_status push( value_type const& va) {
- typename allocator_traits_t::pointer ptr{
- allocator_traits_t::allocate( alloc_, 1) };
- try {
- allocator_traits_t::construct( alloc_, ptr, va, alloc_);
- } catch (...) {
- allocator_traits_t::deallocate( alloc_, ptr, 1);
- throw;
- }
- std::unique_lock< mutex > lk( mtx_);
- return push_( { detail::convert( ptr) }, lk);
- }
-
- channel_op_status push( value_type && va) {
- typename allocator_traits_t::pointer ptr{
- allocator_traits_t::allocate( alloc_, 1) };
- try {
- allocator_traits_t::construct(
- alloc_, ptr, std::move( va), alloc_);
- } catch (...) {
- allocator_traits_t::deallocate( alloc_, ptr, 1);
- throw;
- }
- std::unique_lock< mutex > lk( mtx_);
- return push_( { detail::convert( ptr) }, lk);
- }
-
- channel_op_status pop( value_type & va) {
- std::unique_lock< mutex > lk( mtx_);
- not_empty_cond_.wait( lk,
- [this](){
- return is_closed_() || ! is_empty_();
- });
- if ( is_closed_() && is_empty_() ) {
- return channel_op_status::closed;
- }
- va = value_pop_( lk);
- return channel_op_status::success;
- }
-
- value_type value_pop() {
- std::unique_lock< mutex > lk( mtx_);
- not_empty_cond_.wait( lk,
- [this](){
- return is_closed_() || ! is_empty_();
- });
- if ( is_closed_() && is_empty_() ) {
- throw fiber_error(
- std::make_error_code( std::errc::operation_not_permitted),
- "boost fiber: queue is closed");
- }
- return value_pop_( lk);
- }
-
- channel_op_status try_pop( value_type & va) {
- std::unique_lock< mutex > lk( mtx_);
- if ( is_closed_() && is_empty_() ) {
- // let other fibers run
- lk.unlock();
- this_fiber::yield();
- return channel_op_status::closed;
- }
- if ( is_empty_() ) {
- // let other fibers run
- lk.unlock();
- this_fiber::yield();
- return channel_op_status::empty;
- }
- va = value_pop_( lk);
- return channel_op_status::success;
- }
-
- template< typename Rep, typename Period >
- channel_op_status pop_wait_for( value_type & va,
- std::chrono::duration< Rep, Period > const& timeout_duration) {
- return pop_wait_until( va, std::chrono::steady_clock::now() + timeout_duration);
- }
-
- template< typename Clock, typename Duration >
- channel_op_status pop_wait_until( value_type & va,
- std::chrono::time_point< Clock, Duration > const& timeout_time) {
- std::unique_lock< mutex > lk( mtx_);
- if ( ! not_empty_cond_.wait_until( lk, timeout_time,
- [this](){
- return is_closed_() || ! is_empty_();
- })) {
- return channel_op_status::timeout;
- }
- if ( is_closed_() && is_empty_() ) {
- return channel_op_status::closed;
- }
- va = value_pop_( lk);
- return channel_op_status::success;
- }
-};
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_FIBERS_UNBOUNDED_CHANNEL_H
diff --git a/boost/fiber/unbuffered_channel.hpp b/boost/fiber/unbuffered_channel.hpp
index 582d9ae5a7..38a2d6111e 100644
--- a/boost/fiber/unbuffered_channel.hpp
+++ b/boost/fiber/unbuffered_channel.hpp
@@ -54,13 +54,14 @@ private:
};
// shared cacheline
- alignas(cache_alignment) std::atomic< slot * > slot_{ nullptr };
+ alignas(cache_alignment) std::atomic< slot * > slot_{ nullptr };
// shared cacheline
- alignas(cache_alignment) std::atomic_bool closed_{ false };
- mutable detail::spinlock splk_{};
- wait_queue_type waiting_producers_{};
- wait_queue_type waiting_consumers_{};
- char pad_[cacheline_length];
+ alignas(cache_alignment) std::atomic_bool closed_{ false };
+ alignas(cache_alignment) mutable detail::spinlock splk_producers_{};
+ wait_queue_type waiting_producers_{};
+ alignas( cache_alignment) mutable detail::spinlock splk_consumers_{};
+ wait_queue_type waiting_consumers_{};
+ char pad_[cacheline_length];
bool is_empty_() {
return nullptr == slot_.load( std::memory_order_acquire);
@@ -68,7 +69,7 @@ private:
bool try_push_( slot * own_slot) {
for (;;) {
- slot * s{ slot_.load( std::memory_order_acquire) };
+ slot * s = slot_.load( std::memory_order_acquire);
if ( nullptr == s) {
if ( ! slot_.compare_exchange_strong( s, own_slot, std::memory_order_acq_rel) ) {
continue;
@@ -81,9 +82,9 @@ private:
}
slot * try_pop_() {
- slot * nil_slot{ nullptr };
+ slot * nil_slot = nullptr;
for (;;) {
- slot * s{ slot_.load( std::memory_order_acquire) };
+ slot * s = slot_.load( std::memory_order_acquire);
if ( nullptr != s) {
if ( ! slot_.compare_exchange_strong( s, nil_slot, std::memory_order_acq_rel) ) {
continue;}
@@ -97,12 +98,12 @@ public:
~unbuffered_channel() {
close();
- slot * s{ nullptr };
+ 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()->set_ready( s->ctx);
+ context::active()->schedule( s->ctx);
}
}
@@ -114,90 +115,89 @@ public:
}
void close() noexcept {
- context * ctx{ context::active() };
- detail::spinlock_lock lk{ splk_ };
- closed_.store( true, std::memory_order_release);
+ context * active_ctx = context::active();
// notify all waiting producers
+ closed_.store( true, std::memory_order_release);
+ detail::spinlock_lock lk1{ splk_producers_ };
while ( ! waiting_producers_.empty() ) {
- context * producer_ctx{ & waiting_producers_.front() };
+ context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
- ctx->set_ready( producer_ctx);
+ active_ctx->schedule( producer_ctx);
}
// notify all waiting consumers
+ detail::spinlock_lock lk2{ splk_consumers_ };
while ( ! waiting_consumers_.empty() ) {
- context * consumer_ctx{ & waiting_consumers_.front() };
+ context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- ctx->set_ready( consumer_ctx);
+ active_ctx->schedule( consumer_ctx);
}
}
channel_op_status push( value_type const& value) {
- context * ctx{ context::active() };
- slot s{ value, ctx };
+ context * active_ctx = context::active();
+ slot s{ value, active_ctx };
for (;;) {
if ( is_closed() ) {
return channel_op_status::closed;
}
if ( try_push_( & s) ) {
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_consumers_ };
// notify one waiting consumer
if ( ! waiting_consumers_.empty() ) {
- context * consumer_ctx{ & waiting_consumers_.front() };
+ context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- ctx->set_ready( consumer_ctx);
+ active_ctx->schedule( consumer_ctx);
}
// suspend till value has been consumed
- ctx->suspend( lk);
+ active_ctx->suspend( lk);
// resumed, value has been consumed
return channel_op_status::success;
} else {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_producers_ };
if ( is_closed() ) {
return channel_op_status::closed;
}
if ( is_empty_() ) {
continue;
}
- ctx->wait_link( waiting_producers_);
+ active_ctx->wait_link( waiting_producers_);
// suspend this producer
- ctx->suspend( lk);
+ active_ctx->suspend( lk);
// resumed, slot mabye free
}
}
}
channel_op_status push( value_type && value) {
- context * ctx{ context::active() };
- slot s{ std::move( value), ctx };
+ context * active_ctx = context::active();
+ slot s{ std::move( value), active_ctx };
for (;;) {
if ( is_closed() ) {
return channel_op_status::closed;
}
if ( try_push_( & s) ) {
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_consumers_ };
// notify one waiting consumer
if ( ! waiting_consumers_.empty() ) {
- context * consumer_ctx{ & waiting_consumers_.front() };
+ context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- ctx->set_ready( consumer_ctx);
+ active_ctx->schedule( consumer_ctx);
}
// suspend till value has been consumed
- ctx->suspend( lk);
+ active_ctx->suspend( lk);
// resumed, value has been consumed
return channel_op_status::success;
} else {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_producers_ };
if ( is_closed() ) {
return channel_op_status::closed;
}
if ( is_empty_() ) {
continue;
}
- ctx->wait_link( waiting_producers_);
+ active_ctx->wait_link( waiting_producers_);
// suspend this producer
- ctx->suspend( lk);
+ active_ctx->suspend( lk);
// resumed, slot mabye free
}
}
@@ -220,51 +220,46 @@ public:
template< typename Clock, typename Duration >
channel_op_status push_wait_until( value_type const& value,
std::chrono::time_point< Clock, Duration > const& timeout_time_) {
- std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) );
- context * ctx{ context::active() };
- slot s{ value, ctx };
+ context * active_ctx = context::active();
+ slot s{ value, active_ctx };
+ std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
for (;;) {
if ( is_closed() ) {
return channel_op_status::closed;
}
if ( try_push_( & s) ) {
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_consumers_ };
// notify one waiting consumer
if ( ! waiting_consumers_.empty() ) {
- context * consumer_ctx{ & waiting_consumers_.front() };
+ context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- ctx->set_ready( consumer_ctx);
+ active_ctx->schedule( consumer_ctx);
}
// suspend this producer
- if ( ! ctx->wait_until( timeout_time, lk) ) {
+ if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// clear slot
- slot * nil_slot{ nullptr }, * own_slot{ & s };
+ slot * nil_slot = nullptr, * own_slot = & s;
slot_.compare_exchange_strong( own_slot, nil_slot, std::memory_order_acq_rel);
- // relock local lk
- lk.lock();
- // remove from waiting-queue
- ctx->wait_unlink();
// resumed, value has not been consumed
return channel_op_status::timeout;
}
// resumed, value has been consumed
return channel_op_status::success;
} else {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_producers_ };
if ( is_closed() ) {
return channel_op_status::closed;
}
if ( is_empty_() ) {
continue;
}
- ctx->wait_link( waiting_producers_);
+ active_ctx->wait_link( waiting_producers_);
// suspend this producer
- if ( ! ctx->wait_until( timeout_time, lk) ) {
+ if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// relock local lk
lk.lock();
// remove from waiting-queue
- ctx->wait_unlink();
+ waiting_producers_.remove( * active_ctx);
return channel_op_status::timeout;
}
// resumed, slot maybe free
@@ -275,51 +270,46 @@ public:
template< typename Clock, typename Duration >
channel_op_status push_wait_until( value_type && value,
std::chrono::time_point< Clock, Duration > const& timeout_time_) {
- std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) );
- context * ctx{ context::active() };
- slot s{ std::move( value), ctx };
+ context * active_ctx = context::active();
+ slot s{ std::move( value), active_ctx };
+ std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
for (;;) {
if ( is_closed() ) {
return channel_op_status::closed;
}
if ( try_push_( & s) ) {
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_consumers_ };
// notify one waiting consumer
if ( ! waiting_consumers_.empty() ) {
- context * consumer_ctx{ & waiting_consumers_.front() };
+ context * consumer_ctx = & waiting_consumers_.front();
waiting_consumers_.pop_front();
- ctx->set_ready( consumer_ctx);
+ active_ctx->schedule( consumer_ctx);
}
// suspend this producer
- if ( ! ctx->wait_until( timeout_time, lk) ) {
+ if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// clear slot
- slot * nil_slot{ nullptr }, * own_slot{ & s };
+ slot * nil_slot = nullptr, * own_slot = & s;
slot_.compare_exchange_strong( own_slot, nil_slot, std::memory_order_acq_rel);
- // relock local lk
- lk.lock();
- // remove from waiting-queue
- ctx->wait_unlink();
// resumed, value has not been consumed
return channel_op_status::timeout;
}
// resumed, value has been consumed
return channel_op_status::success;
} else {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_producers_ };
if ( is_closed() ) {
return channel_op_status::closed;
}
if ( is_empty_() ) {
continue;
}
- ctx->wait_link( waiting_producers_);
+ active_ctx->wait_link( waiting_producers_);
// suspend this producer
- if ( ! ctx->wait_until( timeout_time, lk) ) {
+ if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// relock local lk
lk.lock();
// remove from waiting-queue
- ctx->wait_unlink();
+ waiting_producers_.remove( * active_ctx);
return channel_op_status::timeout;
}
// resumed, slot maybe free
@@ -328,65 +318,63 @@ public:
}
channel_op_status pop( value_type & value) {
- context * ctx{ context::active() };
- slot * s{ nullptr };
+ context * active_ctx = context::active();
+ slot * s = nullptr;
for (;;) {
if ( nullptr != ( s = try_pop_() ) ) {
{
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_producers_ };
// notify one waiting producer
if ( ! waiting_producers_.empty() ) {
- context * producer_ctx{ & waiting_producers_.front() };
+ context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- ctx->set_ready( producer_ctx);
+ active_ctx->schedule( producer_ctx);
}
}
// consume value
value = std::move( s->value);
// resume suspended producer
- ctx->set_ready( s->ctx);
+ active_ctx->schedule( s->ctx);
return channel_op_status::success;
} else {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_consumers_ };
if ( is_closed() ) {
return channel_op_status::closed;
}
if ( ! is_empty_() ) {
continue;
}
- ctx->wait_link( waiting_consumers_);
+ active_ctx->wait_link( waiting_consumers_);
// suspend this consumer
- ctx->suspend( lk);
+ active_ctx->suspend( lk);
// resumed, slot mabye set
}
}
}
value_type value_pop() {
- context * ctx{ context::active() };
- slot * s{ nullptr };
+ context * active_ctx = context::active();
+ slot * s = nullptr;
for (;;) {
if ( nullptr != ( s = try_pop_() ) ) {
{
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_producers_ };
// notify one waiting producer
if ( ! waiting_producers_.empty() ) {
- context * producer_ctx{ & waiting_producers_.front() };
+ context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- ctx->set_ready( producer_ctx);
+ active_ctx->schedule( producer_ctx);
}
}
// consume value
value_type value{ std::move( s->value) };
// resume suspended producer
- ctx->set_ready( s->ctx);
+ active_ctx->schedule( s->ctx);
return std::move( value);
} else {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_consumers_ };
if ( is_closed() ) {
throw fiber_error{
std::make_error_code( std::errc::operation_not_permitted),
@@ -395,9 +383,9 @@ public:
if ( ! is_empty_() ) {
continue;
}
- ctx->wait_link( waiting_consumers_);
+ active_ctx->wait_link( waiting_consumers_);
// suspend this consumer
- ctx->suspend( lk);
+ active_ctx->suspend( lk);
// resumed, slot mabye set
}
}
@@ -413,42 +401,41 @@ public:
template< typename Clock, typename Duration >
channel_op_status pop_wait_until( value_type & value,
std::chrono::time_point< Clock, Duration > const& timeout_time_) {
- std::chrono::steady_clock::time_point timeout_time( detail::convert( timeout_time_) );
- context * ctx{ context::active() };
- slot * s{ nullptr };
+ context * active_ctx = context::active();
+ slot * s = nullptr;
+ std::chrono::steady_clock::time_point timeout_time = detail::convert( timeout_time_);
for (;;) {
if ( nullptr != ( s = try_pop_() ) ) {
{
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_producers_ };
// notify one waiting producer
if ( ! waiting_producers_.empty() ) {
- context * producer_ctx{ & waiting_producers_.front() };
+ context * producer_ctx = & waiting_producers_.front();
waiting_producers_.pop_front();
lk.unlock();
- ctx->set_ready( producer_ctx);
+ active_ctx->schedule( producer_ctx);
}
}
// consume value
value = std::move( s->value);
// resume suspended producer
- ctx->set_ready( s->ctx);
+ active_ctx->schedule( s->ctx);
return channel_op_status::success;
} else {
- BOOST_ASSERT( ! ctx->wait_is_linked() );
- detail::spinlock_lock lk{ splk_ };
+ detail::spinlock_lock lk{ splk_consumers_ };
if ( is_closed() ) {
return channel_op_status::closed;
}
if ( ! is_empty_() ) {
continue;
}
- ctx->wait_link( waiting_consumers_);
+ active_ctx->wait_link( waiting_consumers_);
// suspend this consumer
- if ( ! ctx->wait_until( timeout_time, lk) ) {
+ if ( ! active_ctx->wait_until( timeout_time, lk) ) {
// relock local lk
lk.lock();
// remove from waiting-queue
- ctx->wait_unlink();
+ waiting_consumers_.remove( * active_ctx);
return channel_op_status::timeout;
}
}
@@ -459,8 +446,8 @@ public:
private:
typedef typename std::aligned_storage< sizeof( value_type), alignof( value_type) >::type storage_type;
- unbuffered_channel * chan_{ nullptr };
- storage_type storage_;
+ unbuffered_channel * chan_{ nullptr };
+ storage_type storage_;
void increment_() {
BOOST_ASSERT( nullptr != chan_);
diff --git a/boost/filesystem/detail/macro_value.hpp b/boost/filesystem/detail/macro_value.hpp
new file mode 100644
index 0000000000..2c4a16a628
--- /dev/null
+++ b/boost/filesystem/detail/macro_value.hpp
@@ -0,0 +1,44 @@
+// boost/filesystem/detail/macro_value.hpp -------------------------------------------//
+
+// (C) Copyright John Maddock 2001 - 2003
+// (C) Copyright Jens Maurer 2001
+// (C) Copyright Peter Dimov 2001
+// (C) Copyright Darin Adler 2001
+// (C) Copyright Beman Dawes 2002
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+// Library home page: http://www.boost.org/libs/filesystem
+
+//--------------------------------------------------------------------------------------//
+
+#ifndef BOOST_FILESYSTEM_MACRO_VALUE_HPP
+#define BOOST_FILESYSTEM_MACRO_VALUE_HPP
+
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <cstdlib>
+
+namespace boost
+{
+ namespace detail
+ {
+ inline const char* macro_value(const char* name, const char* value)
+ {
+ static const char* no_value = "[no value]";
+ static const char* not_defined = "[not defined]";
+
+ BOOST_ASSERT_MSG(name, "name argument must not be a null pointer");
+ BOOST_ASSERT_MSG(value, "value argument must not be a null pointer");
+
+ return strcmp(name, value + 1)
+ ? ((*value && *(value+1)) ? (value+1) : no_value)
+ : not_defined; // name == value+1 so the macro is not defined
+ }
+ } // detail
+} // boost
+
+#define BOOST_MACRO_VALUE(X) boost::detail::macro_value(#X, BOOST_STRINGIZE(=X))
+
+#endif // BOOST_FILESYSTEM_MACRO_VALUE_HPP
diff --git a/boost/function/function_template.hpp b/boost/function/function_template.hpp
index 82c81d7697..7984c8323f 100644
--- a/boost/function/function_template.hpp
+++ b/boost/function/function_template.hpp
@@ -656,17 +656,6 @@ namespace boost {
BOOST_FUNCTION_TEMPLATE_PARMS
>
class BOOST_FUNCTION_FUNCTION : public function_base
-
-#if BOOST_FUNCTION_NUM_ARGS == 1
-
- , public std::unary_function<T0,R>
-
-#elif BOOST_FUNCTION_NUM_ARGS == 2
-
- , public std::binary_function<T0,T1,R>
-
-#endif
-
{
public:
#ifndef BOOST_NO_VOID_RETURNS
diff --git a/boost/functional.hpp b/boost/functional.hpp
index b618485c10..6443078470 100644
--- a/boost/functional.hpp
+++ b/boost/functional.hpp
@@ -18,6 +18,36 @@
namespace boost
{
+ namespace functional
+ {
+ namespace detail {
+#if defined(_HAS_AUTO_PTR_ETC) && !_HAS_AUTO_PTR_ETC
+ // std::unary_function and std::binary_function were both removed
+ // in C++17.
+
+ template <typename Arg1, typename Result>
+ struct unary_function
+ {
+ typedef Arg1 argument_type;
+ typedef Result result_type;
+ };
+
+ template <typename Arg1, typename Arg2, typename Result>
+ struct binary_function
+ {
+ typedef Arg1 first_argument_type;
+ typedef Arg2 second_argument_type;
+ typedef Result result_type;
+ };
+#else
+ // Use the standard objects when we have them.
+
+ using std::unary_function;
+ using std::binary_function;
+#endif
+ }
+ }
+
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// --------------------------------------------------------------------------
// The following traits classes allow us to avoid the need for ptr_fun
@@ -147,7 +177,7 @@ namespace boost
// --------------------------------------------------------------------------
template <class Predicate>
class unary_negate
- : public std::unary_function<typename unary_traits<Predicate>::argument_type,bool>
+ : public boost::functional::detail::unary_function<typename unary_traits<Predicate>::argument_type,bool>
{
public:
explicit unary_negate(typename unary_traits<Predicate>::param_type x)
@@ -181,7 +211,8 @@ namespace boost
// --------------------------------------------------------------------------
template <class Predicate>
class binary_negate
- : public std::binary_function<typename binary_traits<Predicate>::first_argument_type,
+ : public boost::functional::detail::binary_function<
+ typename binary_traits<Predicate>::first_argument_type,
typename binary_traits<Predicate>::second_argument_type,
bool>
{
@@ -218,7 +249,8 @@ namespace boost
// --------------------------------------------------------------------------
template <class Operation>
class binder1st
- : public std::unary_function<typename binary_traits<Operation>::second_argument_type,
+ : public boost::functional::detail::unary_function<
+ typename binary_traits<Operation>::second_argument_type,
typename binary_traits<Operation>::result_type>
{
public:
@@ -264,7 +296,8 @@ namespace boost
// --------------------------------------------------------------------------
template <class Operation>
class binder2nd
- : public std::unary_function<typename binary_traits<Operation>::first_argument_type,
+ : public boost::functional::detail::unary_function<
+ typename binary_traits<Operation>::first_argument_type,
typename binary_traits<Operation>::result_type>
{
public:
@@ -309,7 +342,7 @@ namespace boost
// mem_fun, etc
// --------------------------------------------------------------------------
template <class S, class T>
- class mem_fun_t : public std::unary_function<T*, S>
+ class mem_fun_t : public boost::functional::detail::unary_function<T*, S>
{
public:
explicit mem_fun_t(S (T::*p)())
@@ -325,7 +358,7 @@ namespace boost
};
template <class S, class T, class A>
- class mem_fun1_t : public std::binary_function<T*, A, S>
+ class mem_fun1_t : public boost::functional::detail::binary_function<T*, A, S>
{
public:
explicit mem_fun1_t(S (T::*p)(A))
@@ -341,7 +374,7 @@ namespace boost
};
template <class S, class T>
- class const_mem_fun_t : public std::unary_function<const T*, S>
+ class const_mem_fun_t : public boost::functional::detail::unary_function<const T*, S>
{
public:
explicit const_mem_fun_t(S (T::*p)() const)
@@ -357,7 +390,7 @@ namespace boost
};
template <class S, class T, class A>
- class const_mem_fun1_t : public std::binary_function<const T*, A, S>
+ class const_mem_fun1_t : public boost::functional::detail::binary_function<const T*, A, S>
{
public:
explicit const_mem_fun1_t(S (T::*p)(A) const)
@@ -402,7 +435,7 @@ namespace boost
// mem_fun_ref, etc
// --------------------------------------------------------------------------
template <class S, class T>
- class mem_fun_ref_t : public std::unary_function<T&, S>
+ class mem_fun_ref_t : public boost::functional::detail::unary_function<T&, S>
{
public:
explicit mem_fun_ref_t(S (T::*p)())
@@ -418,7 +451,7 @@ namespace boost
};
template <class S, class T, class A>
- class mem_fun1_ref_t : public std::binary_function<T&, A, S>
+ class mem_fun1_ref_t : public boost::functional::detail::binary_function<T&, A, S>
{
public:
explicit mem_fun1_ref_t(S (T::*p)(A))
@@ -434,7 +467,7 @@ namespace boost
};
template <class S, class T>
- class const_mem_fun_ref_t : public std::unary_function<const T&, S>
+ class const_mem_fun_ref_t : public boost::functional::detail::unary_function<const T&, S>
{
public:
explicit const_mem_fun_ref_t(S (T::*p)() const)
@@ -451,7 +484,7 @@ namespace boost
};
template <class S, class T, class A>
- class const_mem_fun1_ref_t : public std::binary_function<const T&, A, S>
+ class const_mem_fun1_ref_t : public boost::functional::detail::binary_function<const T&, A, S>
{
public:
explicit const_mem_fun1_ref_t(S (T::*p)(A) const)
@@ -497,7 +530,7 @@ namespace boost
// ptr_fun
// --------------------------------------------------------------------------
template <class Arg, class Result>
- class pointer_to_unary_function : public std::unary_function<Arg,Result>
+ class pointer_to_unary_function : public boost::functional::detail::unary_function<Arg,Result>
{
public:
explicit pointer_to_unary_function(Result (*f)(Arg))
@@ -521,7 +554,7 @@ namespace boost
}
template <class Arg1, class Arg2, class Result>
- class pointer_to_binary_function : public std::binary_function<Arg1,Arg2,Result>
+ class pointer_to_binary_function : public boost::functional::detail::binary_function<Arg1,Arg2,Result>
{
public:
explicit pointer_to_binary_function(Result (*f)(Arg1, Arg2))
diff --git a/boost/functional/hash/extensions.hpp b/boost/functional/hash/extensions.hpp
index eafaefe85d..cb3c85623b 100644
--- a/boost/functional/hash/extensions.hpp
+++ b/boost/functional/hash/extensions.hpp
@@ -254,7 +254,7 @@ namespace boost
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <class T> struct hash
- : std::unary_function<T, std::size_t>
+ : boost::hash_detail::hash_base<T>
{
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
std::size_t operator()(T const& val) const
@@ -271,7 +271,7 @@ namespace boost
#if BOOST_WORKAROUND(__DMC__, <= 0x848)
template <class T, unsigned int n> struct hash<T[n]>
- : std::unary_function<T[n], std::size_t>
+ : boost::hash_detail::hash_base<T[n]>
{
std::size_t operator()(const T* val) const
{
@@ -296,7 +296,7 @@ namespace boost
{
template <class T>
struct inner
- : std::unary_function<T, std::size_t>
+ : boost::hash_detail::hash_base<T>
{
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
std::size_t operator()(T const& val) const
diff --git a/boost/functional/hash/hash.hpp b/boost/functional/hash/hash.hpp
index 5bba40892d..76c4897ebe 100644
--- a/boost/functional/hash/hash.hpp
+++ b/boost/functional/hash/hash.hpp
@@ -62,6 +62,18 @@ namespace boost
{
namespace hash_detail
{
+#if defined(_HAS_AUTO_PTR_ETC) && !_HAS_AUTO_PTR_ETC
+ template <typename T>
+ struct hash_base
+ {
+ typedef T argument_type;
+ typedef std::size_t result_type;
+ };
+#else
+ template <typename T>
+ struct hash_base : std::unary_function<T, std::size_t> {};
+#endif
+
struct enable_hash_value { typedef std::size_t type; };
template <typename T> struct basic_numbers {};
@@ -419,7 +431,7 @@ namespace boost
#define BOOST_HASH_SPECIALIZE(type) \
template <> struct hash<type> \
- : public std::unary_function<type, std::size_t> \
+ : public boost::hash_detail::hash_base<type> \
{ \
std::size_t operator()(type v) const \
{ \
@@ -429,7 +441,7 @@ namespace boost
#define BOOST_HASH_SPECIALIZE_REF(type) \
template <> struct hash<type> \
- : public std::unary_function<type, std::size_t> \
+ : public boost::hash_detail::hash_base<type> \
{ \
std::size_t operator()(type const& v) const \
{ \
@@ -483,7 +495,7 @@ namespace boost
template <class T>
struct hash<T*>
- : public std::unary_function<T*, std::size_t>
+ : public boost::hash_detail::hash_base<T*>
{
std::size_t operator()(T* v) const
{
@@ -516,7 +528,7 @@ namespace boost
{
template <class T>
struct inner
- : public std::unary_function<T, std::size_t>
+ : public boost::hash_detail::hash_base<T>
{
std::size_t operator()(T val) const
{
diff --git a/boost/geometry/algorithms/area.hpp b/boost/geometry/algorithms/area.hpp
index 4751d4e742..18aea24036 100644
--- a/boost/geometry/algorithms/area.hpp
+++ b/boost/geometry/algorithms/area.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.
@@ -303,7 +307,8 @@ inline typename default_area_result<Geometry>::type area(Geometry const& geometr
[heading Available Strategies]
\* [link geometry.reference.strategies.strategy_area_surveyor Surveyor (cartesian)]
-\* [link geometry.reference.strategies.strategy_area_huiller Huiller (spherical)]
+\* [link geometry.reference.strategies.strategy_area_spherical Spherical]
+[/link geometry.reference.strategies.strategy_area_geographic Geographic]
}
*/
template <typename Geometry, typename Strategy>
diff --git a/boost/geometry/algorithms/buffer.hpp b/boost/geometry/algorithms/buffer.hpp
index e1d3c20e44..fd6f0fbe6a 100644
--- a/boost/geometry/algorithms/buffer.hpp
+++ b/boost/geometry/algorithms/buffer.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.
@@ -274,6 +278,11 @@ inline void buffer(GeometryIn const& geometry_in,
geometry::envelope(geometry_in, box);
geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
+ typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<GeometryIn>::type
+ >::type intersection_strategy;
+
rescale_policy_type rescale_policy
= boost::geometry::get_rescale_policy<rescale_policy_type>(box);
@@ -283,6 +292,7 @@ inline void buffer(GeometryIn const& geometry_in,
join_strategy,
end_strategy,
point_strategy,
+ intersection_strategy,
rescale_policy);
}
diff --git a/boost/geometry/algorithms/centroid.hpp b/boost/geometry/algorithms/centroid.hpp
index fc2908ab1c..6a58033f37 100644
--- a/boost/geometry/algorithms/centroid.hpp
+++ b/boost/geometry/algorithms/centroid.hpp
@@ -3,7 +3,7 @@
// 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.
+// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015.
// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
@@ -26,6 +26,7 @@
#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
@@ -183,7 +184,7 @@ inline bool range_ok(Range const& range, Point& centroid)
else if (n <= 0)
{
#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
- throw centroid_exception();
+ BOOST_THROW_EXCEPTION(centroid_exception());
#else
return false;
#endif
@@ -366,7 +367,7 @@ struct centroid_multi
// to calculate the centroid
if (geometry::is_empty(multi))
{
- throw centroid_exception();
+ BOOST_THROW_EXCEPTION(centroid_exception());
}
#endif
diff --git a/boost/geometry/algorithms/covered_by.hpp b/boost/geometry/algorithms/covered_by.hpp
index 2001d5810c..f9d9dcc486 100644
--- a/boost/geometry/algorithms/covered_by.hpp
+++ b/boost/geometry/algorithms/covered_by.hpp
@@ -4,8 +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 2013, 2014.
-// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.
+// 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.
@@ -14,8 +16,6 @@
// 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_COVERED_BY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
@@ -51,9 +51,13 @@ struct use_point_in_geometry
struct use_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/)
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
- return Strategy::apply(geometry1, geometry2);
+ typedef typename detail::de9im::static_mask_covered_by_type
+ <
+ Geometry1, Geometry2
+ >::type covered_by_mask;
+ return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
}
};
@@ -281,23 +285,8 @@ struct covered_by
Geometry2 const& geometry2,
default_strategy)
{
- typedef typename point_type<Geometry1>::type point_type1;
- typedef typename point_type<Geometry2>::type point_type2;
-
typedef typename strategy::covered_by::services::default_strategy
<
- typename tag<Geometry1>::type,
- typename tag<Geometry2>::type,
- typename tag<Geometry1>::type,
- typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
- typename tag_cast
- <
- typename cs_tag<point_type1>::type, spherical_tag
- >::type,
- typename tag_cast
- <
- typename cs_tag<point_type2>::type, spherical_tag
- >::type,
Geometry1,
Geometry2
>::type strategy_type;
diff --git a/boost/geometry/algorithms/crosses.hpp b/boost/geometry/algorithms/crosses.hpp
index 73d86ef529..c9e3651ab2 100644
--- a/boost/geometry/algorithms/crosses.hpp
+++ b/boost/geometry/algorithms/crosses.hpp
@@ -5,8 +5,10 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
-// 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -15,8 +17,6 @@
// 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_CROSSES_HPP
#define BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP
@@ -26,12 +26,12 @@
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/core/access.hpp>
-
#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
-#include <boost/geometry/algorithms/relate.hpp>
-#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
namespace boost { namespace geometry
{
@@ -62,20 +62,51 @@ struct crosses
#endif // DOXYGEN_NO_DISPATCH
+namespace resolve_strategy
+{
+
+struct crosses
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+
+ return dispatch::crosses<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 apply(geometry1, geometry2, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2>
struct crosses
{
- static inline bool
- apply(
- const Geometry1& geometry1,
- const Geometry2& geometry2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
- return dispatch::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ return resolve_strategy::crosses::apply(geometry1, geometry2, strategy);
}
};
@@ -83,12 +114,15 @@ namespace resolve_variant
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct crosses<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)
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2)
+ , m_strategy(strategy)
{}
template <typename Geometry1>
@@ -98,15 +132,16 @@ namespace resolve_variant
<
Geometry1,
Geometry2
- >::apply(geometry1, m_geometry2);
+ >::apply(geometry1, m_geometry2, m_strategy);
}
};
- static inline bool
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2)
+ template <typename Strategy>
+ static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(geometry2), geometry1);
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
@@ -114,12 +149,15 @@ namespace resolve_variant
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct crosses<Geometry1, 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)
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1)
+ , m_strategy(strategy)
{}
template <typename Geometry2>
@@ -129,15 +167,16 @@ namespace resolve_variant
<
Geometry1,
Geometry2
- >::apply(m_geometry1, geometry2);
+ >::apply(m_geometry1, geometry2, m_strategy);
}
};
- static inline bool
- apply(Geometry1 const& geometry1,
- const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(geometry1), geometry2);
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
@@ -145,8 +184,15 @@ namespace resolve_variant
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, 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>
result_type operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
@@ -155,15 +201,16 @@ namespace resolve_variant
<
Geometry1,
Geometry2
- >::apply(geometry1, geometry2);
+ >::apply(geometry1, geometry2, m_strategy);
}
};
- static inline bool
- apply(const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
- const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2)
+ template <typename Strategy>
+ static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
@@ -175,6 +222,31 @@ namespace resolve_variant
\ingroup crosses
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Crosses}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{crosses}
+\return \return_check2{crosses}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/crosses.qbk]}
+*/
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool crosses(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ return resolve_variant::crosses
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
+}
+
+/*!
+\brief \brief_check2{crosses}
+\ingroup crosses
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{crosses}
@@ -184,7 +256,10 @@ namespace resolve_variant
template <typename Geometry1, typename Geometry2>
inline bool crosses(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ return resolve_variant::crosses
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, default_strategy());
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/azimuth.hpp b/boost/geometry/algorithms/detail/azimuth.hpp
index 7e0d1691ed..a5863d7d24 100644
--- a/boost/geometry/algorithms/detail/azimuth.hpp
+++ b/boost/geometry/algorithms/detail/azimuth.hpp
@@ -2,9 +2,10 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2016.
-// Modifications copyright (c) 2014-2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016, 2017.
+// Modifications copyright (c) 2014-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,
@@ -23,6 +24,7 @@
#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/formulas/spherical.hpp>
#include <boost/geometry/formulas/vincenty_inverse.hpp>
namespace boost { namespace geometry
@@ -69,22 +71,9 @@ struct azimuth<ReturnType, spherical_equatorial_tag>
template <typename P1, typename P2, typename Sphere>
static inline ReturnType apply(P1 const& p1, P2 const& p2, Sphere const& /*unused*/)
{
- // http://williams.best.vwh.net/avform.htm#Crs
- ReturnType dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
- ReturnType cos_p2lat = cos(get_as_radian<1>(p2));
-
- // An optimization which should kick in often for Boxes
- //if ( math::equals(dlon, ReturnType(0)) )
- //if ( get<0>(p1) == get<0>(p2) )
- //{
- // return - sin(get_as_radian<1>(p1)) * cos_p2lat);
- //}
-
- // "An alternative formula, not requiring the pre-computation of d"
- // In the formula below dlon is used as "d"
- return atan2(sin(dlon) * cos_p2lat,
- cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))
- - sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));
+ return geometry::formula::spherical_azimuth<ReturnType, false>
+ ( get_as_radian<0>(p1), get_as_radian<1>(p1),
+ get_as_radian<0>(p2), get_as_radian<1>(p2)).azimuth;
}
template <typename P1, typename P2>
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
index 8447532a6c..029053dda3 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
@@ -2,6 +2,10 @@
// 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)
@@ -449,13 +453,14 @@ struct buffer_inserter<point_tag, Point, RingOutput>
}
};
-
+// Not a specialization, but called from specializations of ring and of polygon.
+// Calling code starts/finishes ring before/after apply
template
<
typename RingInput,
typename RingOutput
>
-struct buffer_inserter<ring_tag, RingInput, RingOutput>
+struct buffer_inserter_ring
{
typedef typename point_type<RingOutput>::type output_point_type;
@@ -568,6 +573,43 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
template
<
+ typename RingInput,
+ typename RingOutput
+>
+struct buffer_inserter<ring_tag, RingInput, RingOutput>
+{
+ template
+ <
+ typename Collection,
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy,
+ typename RobustPolicy
+ >
+ static inline 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)
+ {
+ collection.start_new_ring();
+ 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);
+ collection.finish_ring(code);
+ return code;
+ }
+};
+
+template
+<
typename Linestring,
typename Polygon
>
@@ -709,7 +751,7 @@ private:
typedef typename ring_type<PolygonInput>::type input_ring_type;
typedef typename ring_type<PolygonOutput>::type output_ring_type;
- typedef buffer_inserter<ring_tag, input_ring_type, output_ring_type> policy;
+ typedef buffer_inserter_ring<input_ring_type, output_ring_type> policy;
template
@@ -854,6 +896,7 @@ template
typename JoinStrategy,
typename EndStrategy,
typename PointStrategy,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename VisitPiecesPolicy
>
@@ -863,6 +906,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& point_strategy,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
VisitPiecesPolicy& visit_pieces_policy
)
@@ -872,9 +916,10 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
typedef detail::buffer::buffered_piece_collection
<
typename geometry::ring_type<GeometryOutput>::type,
+ IntersectionStrategy,
RobustPolicy
> collection_type;
- collection_type collection(robust_policy);
+ collection_type collection(intersection_strategy, robust_policy);
collection_type const& const_collection = collection;
bool const areal = boost::is_same
@@ -961,6 +1006,7 @@ template
typename JoinStrategy,
typename EndStrategy,
typename PointStrategy,
+ typename IntersectionStrategy,
typename RobustPolicy
>
inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out,
@@ -969,13 +1015,14 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& point_strategy,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy)
{
detail::buffer::visit_pieces_default_policy visitor;
buffer_inserter<GeometryOutput>(geometry_input, out,
distance_strategy, side_strategy, join_strategy,
end_strategy, point_strategy,
- robust_policy, visitor);
+ intersection_strategy, robust_policy, visitor);
}
#endif // DOXYGEN_NO_DETAIL
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
index c1f04f93b5..92dcdcc7b0 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
@@ -2,6 +2,10 @@
// 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)
@@ -52,6 +56,7 @@ public :
typename Rings,
typename Turns,
typename Geometry,
+ typename Strategy,
typename RobustPolicy,
typename Visitor
>
@@ -63,6 +68,7 @@ public :
detail::overlay::traverse_error_type /*traverse_error*/,
Geometry const& ,
Geometry const& ,
+ Strategy const& ,
RobustPolicy const& ,
state_type& state,
Visitor& /*visitor*/
diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
index e7214428e6..7fbbb790bb 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2016.
-// Modifications copyright (c) 2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016-2017.
+// Modifications copyright (c) 2016-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,
@@ -117,10 +117,13 @@ enum segment_relation_code
*/
-template <typename Ring, typename RobustPolicy>
+template <typename Ring, typename IntersectionStrategy, typename RobustPolicy>
struct buffered_piece_collection
{
- typedef buffered_piece_collection<Ring, RobustPolicy> this_type;
+ typedef buffered_piece_collection
+ <
+ Ring, IntersectionStrategy, RobustPolicy
+ > this_type;
typedef typename geometry::point_type<Ring>::type point_type;
typedef typename geometry::coordinate_type<Ring>::type coordinate_type;
@@ -303,7 +306,7 @@ struct buffered_piece_collection
cluster_type m_clusters;
-
+ IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_robust_policy;
struct redundant_turn
@@ -314,8 +317,10 @@ struct buffered_piece_collection
}
};
- buffered_piece_collection(RobustPolicy const& robust_policy)
+ buffered_piece_collection(IntersectionStrategy const& intersection_strategy,
+ RobustPolicy const& robust_policy)
: m_first_piece_index(-1)
+ , m_intersection_strategy(intersection_strategy)
, m_robust_policy(robust_policy)
{}
@@ -512,10 +517,11 @@ struct buffered_piece_collection
geometry::partition
<
robust_box_type,
- turn_get_box, turn_in_original_ovelaps_box,
- original_get_box, original_ovelaps_box,
- include_turn_policy, detail::partition::include_all_policy
- >::apply(m_turns, robust_originals, visitor);
+ include_turn_policy,
+ detail::partition::include_all_policy
+ >::apply(m_turns, robust_originals, visitor,
+ turn_get_box(), turn_in_original_ovelaps_box(),
+ original_get_box(), original_ovelaps_box());
bool const deflate = distance_strategy.negative();
@@ -767,15 +773,17 @@ struct buffered_piece_collection
piece_vector_type,
buffered_ring_collection<buffered_ring<Ring> >,
turn_vector_type,
+ IntersectionStrategy,
RobustPolicy
- > visitor(m_pieces, offsetted_rings, m_turns, m_robust_policy);
+ > visitor(m_pieces, offsetted_rings, m_turns,
+ m_intersection_strategy, m_robust_policy);
geometry::partition
<
- robust_box_type,
- detail::section::get_section_box,
- detail::section::overlaps_section_box
- >::apply(monotonic_sections, visitor);
+ robust_box_type
+ >::apply(monotonic_sections, visitor,
+ detail::section::get_section_box(),
+ detail::section::overlaps_section_box());
}
insert_rescaled_piece_turns();
@@ -795,10 +803,10 @@ struct buffered_piece_collection
geometry::partition
<
- robust_box_type,
- turn_get_box, turn_ovelaps_box,
- piece_get_box, piece_ovelaps_box
- >::apply(m_turns, m_pieces, visitor);
+ robust_box_type
+ >::apply(m_turns, m_pieces, visitor,
+ turn_get_box(), turn_ovelaps_box(),
+ piece_get_box(), piece_ovelaps_box());
}
}
@@ -1354,7 +1362,8 @@ struct buffered_piece_collection
traversed_rings.clear();
buffer_overlay_visitor visitor;
traverser::apply(offsetted_rings, offsetted_rings,
- m_robust_policy, m_turns, traversed_rings,
+ m_intersection_strategy, m_robust_policy,
+ m_turns, traversed_rings,
m_clusters, visitor);
}
diff --git a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
index 3425ee6ffd..178c7bcafe 100644
--- a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
+++ b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
@@ -2,6 +2,10 @@
// 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)
@@ -62,6 +66,7 @@ template
typename Pieces,
typename Rings,
typename Turns,
+ typename IntersectionStrategy,
typename RobustPolicy
>
class piece_turn_visitor
@@ -69,6 +74,7 @@ class piece_turn_visitor
Pieces const& m_pieces;
Rings const& m_rings;
Turns& m_turns;
+ IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_robust_policy;
template <typename Piece>
@@ -243,7 +249,9 @@ class piece_turn_visitor
turn_policy::apply(*prev1, *it1, *next1,
*prev2, *it2, *next2,
false, false, false, false,
- the_model, m_robust_policy,
+ the_model,
+ m_intersection_strategy,
+ m_robust_policy,
std::back_inserter(m_turns));
}
}
@@ -254,10 +262,12 @@ public:
piece_turn_visitor(Pieces const& pieces,
Rings const& ring_collection,
Turns& turns,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy)
: m_pieces(pieces)
, m_rings(ring_collection)
, m_turns(turns)
+ , m_intersection_strategy(intersection_strategy)
, m_robust_policy(robust_policy)
{}
diff --git a/boost/geometry/algorithms/detail/calculate_sum.hpp b/boost/geometry/algorithms/detail/calculate_sum.hpp
index b23e70171b..732a2f5753 100644
--- a/boost/geometry/algorithms/detail/calculate_sum.hpp
+++ b/boost/geometry/algorithms/detail/calculate_sum.hpp
@@ -8,6 +8,10 @@
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2016.
+// Modifications copyright (c) 2016 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, 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)
@@ -30,7 +34,7 @@ class calculate_polygon_sum
template <typename ReturnType, typename Policy, typename Rings, typename Strategy>
static inline ReturnType sum_interior_rings(Rings const& rings, Strategy const& strategy)
{
- ReturnType sum = ReturnType();
+ ReturnType sum = ReturnType(0);
for (typename boost::range_iterator<Rings const>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
{
diff --git a/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp b/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp
index 284858a130..664c995384 100644
--- a/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/areal_areal.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
@@ -39,15 +39,45 @@ namespace detail { namespace disjoint
{
-template<typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct check_each_ring_for_within_call_covered_by
+{
+ /*!
+ \tparam Strategy point_in_geometry strategy
+ */
+ template <typename Point, typename Strategy>
+ static inline bool apply(Point const& p, Geometry const& g, Strategy const& strategy)
+ {
+ return geometry::covered_by(p, g, strategy);
+ }
+};
+
+template <typename Geometry>
+struct check_each_ring_for_within_call_covered_by<Geometry, box_tag>
+{
+ template <typename Point, typename Strategy>
+ static inline bool apply(Point const& p, Geometry const& g, Strategy const& )
+ {
+ return geometry::covered_by(p, g);
+ }
+};
+
+
+/*!
+\tparam Strategy point_in_geometry strategy
+*/
+template<typename Geometry, typename Strategy>
struct check_each_ring_for_within
{
bool not_disjoint;
Geometry const& m_geometry;
+ Strategy const& m_strategy;
- inline check_each_ring_for_within(Geometry const& g)
+ inline check_each_ring_for_within(Geometry const& g,
+ Strategy const& strategy)
: not_disjoint(false)
, m_geometry(g)
+ , m_strategy(strategy)
{}
template <typename Range>
@@ -56,17 +86,26 @@ struct check_each_ring_for_within
typename point_type<Range>::type pt;
not_disjoint = not_disjoint
|| ( geometry::point_on_border(pt, range)
- && geometry::covered_by(pt, m_geometry) );
+ && check_each_ring_for_within_call_covered_by
+ <
+ Geometry
+ >::apply(pt, m_geometry, m_strategy) );
}
};
-
-template <typename FirstGeometry, typename SecondGeometry>
+/*!
+\tparam Strategy point_in_geometry strategy
+*/
+template <typename FirstGeometry, typename SecondGeometry, typename Strategy>
inline bool rings_containing(FirstGeometry const& geometry1,
- SecondGeometry const& geometry2)
+ SecondGeometry const& geometry2,
+ Strategy const& strategy)
{
- check_each_ring_for_within<FirstGeometry> checker(geometry1);
+ check_each_ring_for_within
+ <
+ FirstGeometry, Strategy
+ > checker(geometry1, strategy);
geometry::detail::for_each_range(geometry2, checker);
return checker.not_disjoint;
}
@@ -76,10 +115,15 @@ inline bool rings_containing(FirstGeometry const& geometry1,
template <typename Geometry1, typename Geometry2>
struct general_areal
{
- static inline
- bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ /*!
+ \tparam Strategy relate (segments intersection) strategy
+ */
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- if ( ! disjoint_linear<Geometry1, Geometry2>::apply(geometry1, geometry2) )
+ if ( ! disjoint_linear<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy) )
{
return false;
}
@@ -90,8 +134,10 @@ struct general_areal
// We check that using a point on the border (external boundary),
// and see if that is contained in the other geometry. And vice versa.
- if ( rings_containing(geometry1, geometry2)
- || rings_containing(geometry2, geometry1) )
+ if ( rings_containing(geometry1, geometry2,
+ strategy.template get_point_in_geometry_strategy<Geometry2, Geometry1>())
+ || rings_containing(geometry2, geometry1,
+ strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>()) )
{
return false;
}
diff --git a/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/boost/geometry/algorithms/detail/disjoint/box_box.hpp
index 3b81755e20..f830f8161c 100644
--- a/boost/geometry/algorithms/detail/disjoint/box_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/box_box.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2016.
-// Modifications copyright (c) 2013-2016, 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
@@ -52,6 +52,12 @@ template
>
struct box_box
{
+ template <typename Strategy>
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
+ {
+ return apply(box1, box2);
+ }
+
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2))
@@ -84,6 +90,12 @@ struct box_box<Box1, Box2, DimensionCount, DimensionCount, CSTag>
template <typename Box1, typename Box2, std::size_t DimensionCount>
struct box_box<Box1, Box2, 0, DimensionCount, spherical_tag>
{
+ template <typename Strategy>
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
+ {
+ return apply(box1, box2);
+ }
+
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
typedef typename geometry::select_most_precise
diff --git a/boost/geometry/algorithms/detail/disjoint/interface.hpp b/boost/geometry/algorithms/detail/disjoint/interface.hpp
index ce7fe6d45c..64898e35fe 100644
--- a/boost/geometry/algorithms/detail/disjoint/interface.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/interface.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
@@ -27,43 +27,51 @@
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
+#include <boost/geometry/algorithms/detail/relate/interface.hpp>
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+
#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+#include <boost/geometry/strategies/disjoint.hpp>
namespace boost { namespace geometry
{
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch
+namespace resolve_strategy
{
-
-// If reversal is needed, perform it
-template
-<
- typename Geometry1, typename Geometry2,
- std::size_t DimensionCount,
- typename Tag1, typename Tag2
->
-struct disjoint<Geometry1, Geometry2, DimensionCount, Tag1, Tag2, true>
+struct disjoint
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- return disjoint
+ return dispatch::disjoint
+ <
+ 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::disjoint::services::default_strategy
<
- Geometry2, Geometry1,
- DimensionCount,
- Tag2, Tag1
- >::apply(g2, g1);
+ Geometry1, Geometry2
+ >::type strategy_type;
+
+ return dispatch::disjoint
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy_type());
}
};
-
-} // namespace dispatch
-#endif // DOXYGEN_NO_DISPATCH
+} // namespace resolve_strategy
namespace resolve_variant {
@@ -71,7 +79,8 @@ namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct disjoint
{
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
concepts::check_concepts_and_equal_dimensions
<
@@ -79,88 +88,135 @@ struct disjoint
Geometry2 const
>();
- return dispatch::disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ return resolve_strategy::disjoint::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct disjoint<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): m_geometry2(geometry2) {}
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_strategy(strategy)
+ {}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
- return disjoint<Geometry1, Geometry2>::apply(geometry1, m_geometry2);
+ return disjoint<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
}
};
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2)
+ 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(geometry2), geometry1);
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct disjoint<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): m_geometry1(geometry1) {}
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_strategy(strategy)
+ {}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
- return disjoint<Geometry1, Geometry2>::apply(m_geometry1, geometry2);
+ return disjoint<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
}
};
- static inline bool
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
+ 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(geometry1), geometry2);
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
-template <
+template
+<
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
-struct disjoint<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
+struct disjoint
+ <
+ 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 disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ return disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
}
};
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
+ 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(), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
} // namespace resolve_variant
+/*!
+\brief \brief_check2{are disjoint}
+\ingroup disjoint
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Disjoint}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{disjoint}
+\return \return_check2{are disjoint}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/disjoint.qbk]}
+*/
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool disjoint(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ return resolve_variant::disjoint
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
+}
+
/*!
\brief \brief_check2{are disjoint}
@@ -177,7 +233,10 @@ template <typename Geometry1, typename Geometry2>
inline bool disjoint(Geometry1 const& geometry1,
Geometry2 const& geometry2)
{
- return resolve_variant::disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ return resolve_variant::disjoint
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp b/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
index 6a48b684a1..e6077d3e7f 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_areal.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-2015.
-// Modifications copyright (c) 2013-2015, 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
@@ -61,19 +61,28 @@ template <typename Geometry1, typename Geometry2,
typename Tag1OrMulti = typename tag_cast<Tag1, multi_tag>::type>
struct disjoint_no_intersections_policy
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ /*!
+ \tparam Strategy point_in_geometry strategy
+ */
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
typedef typename point_type<Geometry1>::type point1_type;
point1_type p;
geometry::point_on_border(p, g1);
- return !geometry::covered_by(p, g2);
+
+ return !geometry::covered_by(p, g2, strategy);
}
};
template <typename Geometry1, typename Geometry2, typename Tag1>
struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ /*!
+ \tparam Strategy point_in_geometry strategy
+ */
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
// TODO: use partition or rtree on g2
typedef typename boost::range_iterator<Geometry1 const>::type iterator;
@@ -81,7 +90,7 @@ struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>
{
typedef typename boost::range_value<Geometry1 const>::type value_type;
if ( ! disjoint_no_intersections_policy<value_type const, Geometry2>
- ::apply(*it, g2) )
+ ::apply(*it, g2, strategy) )
{
return false;
}
@@ -96,15 +105,21 @@ template<typename Geometry1, typename Geometry2,
= disjoint_no_intersections_policy<Geometry1, Geometry2> >
struct disjoint_linear_areal
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ /*!
+ \tparam Strategy relate (segments intersection) strategy
+ */
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
// if there are intersections - return false
- if ( !disjoint_linear<Geometry1, Geometry2>::apply(g1, g2) )
+ if ( !disjoint_linear<Geometry1, Geometry2>::apply(g1, g2, strategy) )
{
return false;
}
- return NoIntersectionsPolicy::apply(g1, g2);
+ return NoIntersectionsPolicy
+ ::apply(g1, g2,
+ strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>());
}
};
@@ -126,16 +141,18 @@ template <typename Segment, typename Polygon>
class disjoint_segment_areal<Segment, Polygon, polygon_tag>
{
private:
- template <typename InteriorRings>
+ template <typename InteriorRings, typename Strategy>
static inline
bool check_interior_rings(InteriorRings const& interior_rings,
- Segment const& segment)
+ Segment const& segment,
+ Strategy const& strategy)
{
typedef typename boost::range_value<InteriorRings>::type ring_type;
typedef unary_disjoint_geometry_to_query_geometry
<
Segment,
+ Strategy,
disjoint_range_segment_or_box
<
ring_type, closure<ring_type>::value, Segment
@@ -147,24 +164,27 @@ private:
unary_predicate_type
>::apply(boost::begin(interior_rings),
boost::end(interior_rings),
- unary_predicate_type(segment));
+ unary_predicate_type(segment, strategy));
}
public:
- static inline bool apply(Segment const& segment, Polygon const& polygon)
+ template <typename IntersectionStrategy>
+ static inline bool apply(Segment const& segment,
+ Polygon const& polygon,
+ IntersectionStrategy const& strategy)
{
typedef typename geometry::ring_type<Polygon>::type ring;
if ( !disjoint_range_segment_or_box
<
ring, closure<Polygon>::value, Segment
- >::apply(geometry::exterior_ring(polygon), segment) )
+ >::apply(geometry::exterior_ring(polygon), segment, strategy) )
{
return false;
}
- if ( !check_interior_rings(geometry::interior_rings(polygon), segment) )
+ if ( !check_interior_rings(geometry::interior_rings(polygon), segment, strategy) )
{
return false;
}
@@ -172,7 +192,8 @@ public:
typename point_type<Segment>::type p;
detail::assign_point_from_index<0>(segment, p);
- return !geometry::covered_by(p, polygon);
+ return !geometry::covered_by(p, polygon,
+ strategy.template get_point_in_geometry_strategy<Segment, Polygon>());
}
};
@@ -180,13 +201,14 @@ public:
template <typename Segment, typename MultiPolygon>
struct disjoint_segment_areal<Segment, MultiPolygon, multi_polygon_tag>
{
- static inline
- bool apply(Segment const& segment, MultiPolygon const& multipolygon)
+ template <typename IntersectionStrategy>
+ static inline bool apply(Segment const& segment, MultiPolygon const& multipolygon,
+ IntersectionStrategy const& strategy)
{
return multirange_constant_size_geometry
<
MultiPolygon, Segment
- >::apply(multipolygon, segment);
+ >::apply(multipolygon, segment, strategy);
}
};
@@ -194,20 +216,24 @@ struct disjoint_segment_areal<Segment, MultiPolygon, multi_polygon_tag>
template <typename Segment, typename Ring>
struct disjoint_segment_areal<Segment, Ring, ring_tag>
{
- static inline bool apply(Segment const& segment, Ring const& ring)
+ template <typename IntersectionStrategy>
+ static inline bool apply(Segment const& segment,
+ Ring const& ring,
+ IntersectionStrategy const& strategy)
{
if ( !disjoint_range_segment_or_box
<
Ring, closure<Ring>::value, Segment
- >::apply(ring, segment) )
+ >::apply(ring, segment, strategy) )
{
return false;
}
typename point_type<Segment>::type p;
detail::assign_point_from_index<0>(segment, p);
-
- return !geometry::covered_by(p, ring);
+
+ return !geometry::covered_by(p, ring,
+ strategy.template get_point_in_geometry_strategy<Segment, Ring>());
}
};
@@ -231,14 +257,15 @@ struct disjoint<Linear, Areal, 2, linear_tag, areal_tag, false>
template <typename Areal, typename Linear>
struct disjoint<Areal, Linear, 2, areal_tag, linear_tag, false>
-{
- static inline
- bool apply(Areal const& areal, Linear const& linear)
+{
+ template <typename Strategy>
+ static inline bool apply(Areal const& areal, Linear const& linear,
+ Strategy const& strategy)
{
return detail::disjoint::disjoint_linear_areal
<
Linear, Areal
- >::apply(linear, areal);
+ >::apply(linear, areal, strategy);
}
};
@@ -246,12 +273,14 @@ struct disjoint<Areal, Linear, 2, areal_tag, linear_tag, false>
template <typename Areal, typename Segment>
struct disjoint<Areal, Segment, 2, areal_tag, segment_tag, false>
{
- static inline bool apply(Areal const& g1, Segment const& g2)
+ template <typename Strategy>
+ static inline bool apply(Areal const& g1, Segment const& g2,
+ Strategy const& strategy)
{
return detail::disjoint::disjoint_segment_areal
<
Segment, Areal
- >::apply(g2, g1);
+ >::apply(g2, g1, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
index 91f985edb8..989b8df247 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_linear.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
@@ -53,7 +53,9 @@ namespace detail { namespace disjoint
template <typename Segment1, typename Segment2>
struct disjoint_segment
{
- static inline bool apply(Segment1 const& segment1, Segment2 const& segment2)
+ template <typename Strategy>
+ static inline bool apply(Segment1 const& segment1, Segment2 const& segment2,
+ Strategy const& strategy)
{
typedef typename point_type<Segment1>::type point_type;
@@ -62,23 +64,23 @@ struct disjoint_segment
rescale_policy_type robust_policy;
typedef segment_intersection_points
- <
- point_type,
- typename segment_ratio_type
+ <
+ point_type,
+ typename segment_ratio_type
<
point_type,
rescale_policy_type
>::type
- > intersection_return_type;
+ > intersection_return_type;
- intersection_return_type is
- = strategy::intersection::relate_cartesian_segments
+ typedef policies::relate::segments_intersection_points
<
- policies::relate::segments_intersection_points
- <
- intersection_return_type
- >
- >::apply(segment1, segment2, robust_policy);
+ intersection_return_type
+ > intersection_policy;
+
+ intersection_return_type is = strategy.apply(segment1, segment2,
+ intersection_policy(),
+ robust_policy);
return is.count == 0;
}
@@ -109,8 +111,10 @@ struct assign_disjoint_policy
template <typename Geometry1, typename Geometry2>
struct disjoint_linear
{
- static inline
- bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
typedef typename geometry::point_type<Geometry1>::type point_type;
typedef detail::no_rescale_policy rescale_policy_type;
@@ -147,7 +151,7 @@ struct disjoint_linear
Geometry1, Geometry2, assign_disjoint_policy
>
>::apply(0, geometry1, 1, geometry2,
- rescale_policy_type(), turns, interrupt_policy);
+ strategy, rescale_policy_type(), turns, interrupt_policy);
return !interrupt_policy.has_intersections;
}
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp b/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp
index 8d82f7c911..b4c71c8f30 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp
@@ -53,8 +53,10 @@ template
>
struct disjoint_range_segment_or_box
{
- static inline
- bool apply(Range const& range, SegmentOrBox const& segment_or_box)
+ template <typename Strategy>
+ static inline bool apply(Range const& range,
+ SegmentOrBox const& segment_or_box,
+ Strategy const& strategy)
{
typedef typename closeable_view<Range const, Closure>::type view_type;
@@ -85,7 +87,8 @@ struct disjoint_range_segment_or_box
<
point_type, SegmentOrBox
>::apply(geometry::range::front<view_type const>(view),
- segment_or_box);
+ segment_or_box,
+ strategy.template get_point_in_geometry_strategy<Range, SegmentOrBox>());
}
else
{
@@ -99,7 +102,7 @@ struct disjoint_range_segment_or_box
if ( !dispatch::disjoint
<
range_segment, SegmentOrBox
- >::apply(rng_segment, segment_or_box) )
+ >::apply(rng_segment, segment_or_box, strategy) )
{
return false;
}
diff --git a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
index 29e438e546..7c1a93cdb7 100644
--- a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.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
@@ -14,8 +15,10 @@
#include <vector>
#include <boost/range.hpp>
+#include <boost/mpl/assert.hpp>
#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/box.hpp>
@@ -105,36 +108,74 @@ template <typename MultiPoint, typename Linear>
class multipoint_linear
{
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);
}
+ };
+ // TODO: After adding non-cartesian Segment envelope to the library
+ // this policy should be modified to take envelope strategy.
+ struct expand_box_segment
+ {
+ template <typename Box, typename Segment>
+ static inline void apply(Box& total, Segment const& segment)
+ {
+ geometry::expand(total, geometry::return_envelope<Box>(segment));
+ }
};
- 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 ! dispatch::disjoint<Geometry, Box>::apply(geometry, box);
+ // 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());
}
};
+ // 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.
+ struct overlaps_box_segment
+ {
+ template <typename Box, typename Segment>
+ static inline bool apply(Box const& box, Segment const& segment)
+ {
+ typedef typename strategy::disjoint::services::default_strategy
+ <
+ Segment, Box
+ >::type strategy_type;
+ return ! dispatch::disjoint<Segment, Box>::apply(segment, box, strategy_type());
+ }
+ };
+
+ template <typename PtSegStrategy>
class item_visitor_type
{
public:
- item_visitor_type() : m_intersection_found(false) {}
+ item_visitor_type(PtSegStrategy const& strategy)
+ : m_intersection_found(false)
+ , m_strategy(strategy)
+ {}
template <typename Item1, typename Item2>
inline void apply(Item1 const& item1, Item2 const& item2)
{
if (! m_intersection_found
- && ! dispatch::disjoint<Item1, Item2>::apply(item1, item2))
+ && ! dispatch::disjoint<Item1, Item2>::apply(item1, item2, m_strategy))
{
m_intersection_found = true;
}
@@ -144,6 +185,7 @@ private:
private:
bool m_intersection_found;
+ PtSegStrategy const& m_strategy;
};
// structs for partition -- end
@@ -172,23 +214,25 @@ private:
};
public:
- static inline bool apply(MultiPoint const& multipoint, Linear const& linear)
+ template <typename Strategy>
+ static inline bool apply(MultiPoint const& multipoint, Linear const& linear, Strategy const& strategy)
{
- item_visitor_type visitor;
+ item_visitor_type<Strategy> visitor(strategy);
geometry::partition
<
- geometry::model::box<typename point_type<MultiPoint>::type>,
- expand_box,
- overlaps_box
- >::apply(multipoint, segment_range(linear), visitor);
+ 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());
return ! visitor.intersection_found();
}
- static inline bool apply(Linear const& linear, MultiPoint const& multipoint)
+ template <typename Strategy>
+ static inline bool apply(Linear const& linear, MultiPoint const& multipoint, Strategy const& strategy)
{
- return apply(multipoint, linear);
+ return apply(multipoint, linear, strategy);
}
};
@@ -240,8 +284,10 @@ struct disjoint
multi_point_tag, multi_point_tag, false
>
{
+ template <typename Strategy>
static inline bool apply(MultiPoint1 const& multipoint1,
- MultiPoint2 const& multipoint2)
+ MultiPoint2 const& multipoint2,
+ Strategy const& )
{
if ( boost::size(multipoint2) < boost::size(multipoint1) )
{
diff --git a/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
index 78a683e46e..53fb1642af 100644
--- a/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
@@ -1,8 +1,9 @@
// 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 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
@@ -25,34 +26,40 @@ namespace detail { namespace disjoint
{
-template <typename Geometry, typename BinaryPredicate>
+template <typename Geometry, typename Strategy, typename BinaryPredicate>
class unary_disjoint_geometry_to_query_geometry
{
public:
- unary_disjoint_geometry_to_query_geometry(Geometry const& geometry)
+ unary_disjoint_geometry_to_query_geometry(Geometry const& geometry,
+ Strategy const& strategy)
: m_geometry(geometry)
+ , m_strategy(strategy)
{}
template <typename QueryGeometry>
inline bool apply(QueryGeometry const& query_geometry) const
{
- return BinaryPredicate::apply(query_geometry, m_geometry);
+ return BinaryPredicate::apply(query_geometry, m_geometry, m_strategy);
}
private:
Geometry const& m_geometry;
+ Strategy const& m_strategy;
};
template<typename MultiRange, typename ConstantSizeGeometry>
struct multirange_constant_size_geometry
{
+ template <typename Strategy>
static inline bool apply(MultiRange const& multirange,
- ConstantSizeGeometry const& constant_size_geometry)
+ ConstantSizeGeometry const& constant_size_geometry,
+ Strategy const& strategy)
{
typedef unary_disjoint_geometry_to_query_geometry
<
ConstantSizeGeometry,
+ Strategy,
dispatch::disjoint
<
typename boost::range_value<MultiRange>::type,
@@ -64,13 +71,15 @@ struct multirange_constant_size_geometry
<
unary_predicate_type
>::apply(boost::begin(multirange), boost::end(multirange),
- unary_predicate_type(constant_size_geometry));
+ unary_predicate_type(constant_size_geometry, strategy));
}
+ template <typename Strategy>
static inline bool apply(ConstantSizeGeometry const& constant_size_geometry,
- MultiRange const& multirange)
+ MultiRange const& multirange,
+ Strategy const& strategy)
{
- return apply(multirange, constant_size_geometry);
+ return apply(multirange, constant_size_geometry, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/disjoint/point_box.hpp b/boost/geometry/algorithms/detail/disjoint/point_box.hpp
index 2f1085ada9..2e6773d221 100644
--- a/boost/geometry/algorithms/detail/disjoint/point_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/point_box.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
-// This file was modified by Oracle on 2013-2016.
-// Modifications copyright (c) 2013-2016, 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
@@ -28,7 +28,7 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
-#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
+#include <boost/geometry/strategies/disjoint.hpp>
namespace boost { namespace geometry
{
@@ -44,13 +44,13 @@ namespace detail { namespace disjoint
template <typename Point, typename Box>
inline bool disjoint_point_box(Point const& point, Box const& box)
{
+ typedef typename strategy::disjoint::services::default_strategy
+ <
+ Point, Box
+ >::type strategy_type;
+
// ! covered_by(point, box)
- return ! strategy::within::relate_point_box_loop
- <
- strategy::within::covered_by_range,
- Point, Box,
- 0, dimension<Point>::type::value
- >::apply(point, box);
+ return ! strategy_type::apply(point, box);
}
@@ -66,15 +66,11 @@ namespace dispatch
template <typename Point, typename Box, std::size_t DimensionCount>
struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, false>
{
- static inline bool apply(Point const& point, Box const& box)
+ template <typename Strategy>
+ static inline bool apply(Point const& point, Box const& box, Strategy const& )
{
// ! covered_by(point, box)
- return ! strategy::within::relate_point_box_loop
- <
- strategy::within::covered_by_range,
- Point, Box,
- 0, DimensionCount
- >::apply(point, box);
+ return ! Strategy::apply(point, box);
}
};
diff --git a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
index 9ae43f73d0..66bd7c26ce 100644
--- a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
@@ -39,11 +39,12 @@ namespace detail { namespace disjoint
struct reverse_covered_by
{
- template <typename Geometry1, typename Geometry2>
- static inline
- bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- return ! geometry::covered_by(geometry1, geometry2);
+ return ! geometry::covered_by(geometry1, geometry2, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/disjoint/point_point.hpp b/boost/geometry/algorithms/detail/disjoint/point_point.hpp
index 7580b7287b..13ac34d718 100644
--- a/boost/geometry/algorithms/detail/disjoint/point_point.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/point_point.hpp
@@ -5,8 +5,8 @@
// 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.
-// 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
@@ -59,6 +59,12 @@ namespace detail { namespace disjoint
template <std::size_t Dimension, std::size_t DimensionCount>
struct point_point_generic
{
+ template <typename Point1, typename Point2, typename Strategy>
+ static inline bool apply(Point1 const& p1, Point2 const& p2, Strategy const& )
+ {
+ return apply(p1, p2);
+ }
+
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& p1, Point2 const& p2)
{
@@ -75,7 +81,7 @@ template <std::size_t DimensionCount>
struct point_point_generic<DimensionCount, DimensionCount>
{
template <typename Point1, typename Point2>
- static inline bool apply(Point1 const&, Point2 const&)
+ static inline bool apply(Point1 const&, Point2 const& )
{
return false;
}
@@ -135,6 +141,12 @@ private:
};
public:
+ template <typename Point1, typename Point2, typename Strategy>
+ static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& )
+ {
+ return apply(point1, point2);
+ }
+
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& point1, Point2 const& point2)
{
diff --git a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
index cc0c7949e3..c2741ce72c 100644
--- a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/segment_box.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
@@ -22,19 +22,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_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/dispatch/disjoint.hpp>
@@ -47,236 +36,19 @@ namespace boost { namespace geometry
namespace detail { namespace disjoint
{
-
-template <std::size_t I>
-struct compute_tmin_tmax_per_dim
-{
- template <typename SegmentPoint, typename Box, typename RelativeDistance>
- static inline void apply(SegmentPoint const& p0,
- SegmentPoint const& p1,
- Box const& box,
- RelativeDistance& ti_min,
- RelativeDistance& ti_max,
- RelativeDistance& diff)
- {
- typedef typename coordinate_type<Box>::type box_coordinate_type;
- typedef typename coordinate_type
- <
- SegmentPoint
- >::type point_coordinate_type;
-
- RelativeDistance c_p0 = boost::numeric_cast
- <
- point_coordinate_type
- >( geometry::get<I>(p0) );
-
- RelativeDistance c_p1 = boost::numeric_cast
- <
- point_coordinate_type
- >( geometry::get<I>(p1) );
-
- RelativeDistance c_b_min = boost::numeric_cast
- <
- box_coordinate_type
- >( geometry::get<geometry::min_corner, I>(box) );
-
- RelativeDistance c_b_max = boost::numeric_cast
- <
- box_coordinate_type
- >( geometry::get<geometry::max_corner, I>(box) );
-
- if ( geometry::get<I>(p1) >= geometry::get<I>(p0) )
- {
- diff = c_p1 - c_p0;
- ti_min = c_b_min - c_p0;
- ti_max = c_b_max - c_p0;
- }
- else
- {
- diff = c_p0 - c_p1;
- ti_min = c_p0 - c_b_max;
- ti_max = c_p0 - c_b_min;
- }
- }
-};
-
-
-template
-<
- typename RelativeDistance,
- typename SegmentPoint,
- typename Box,
- std::size_t I,
- std::size_t Dimension
->
-struct disjoint_segment_box_impl
-{
- template <typename RelativeDistancePair>
- static inline bool apply(SegmentPoint const& p0,
- SegmentPoint const& p1,
- Box const& box,
- RelativeDistancePair& t_min,
- RelativeDistancePair& t_max)
- {
- RelativeDistance ti_min, ti_max, diff;
-
- compute_tmin_tmax_per_dim<I>::apply(p0, p1, box, ti_min, ti_max, diff);
-
- if ( geometry::math::equals(diff, 0) )
- {
- if ( (geometry::math::equals(t_min.second, 0)
- && t_min.first > ti_max)
- ||
- (geometry::math::equals(t_max.second, 0)
- && t_max.first < ti_min)
- ||
- (math::sign(ti_min) * math::sign(ti_max) > 0) )
- {
- return true;
- }
- }
-
- RelativeDistance t_min_x_diff = t_min.first * diff;
- RelativeDistance t_max_x_diff = t_max.first * diff;
-
- if ( t_min_x_diff > ti_max * t_min.second
- || t_max_x_diff < ti_min * t_max.second )
- {
- return true;
- }
-
- if ( ti_min * t_min.second > t_min_x_diff )
- {
- t_min.first = ti_min;
- t_min.second = diff;
- }
- if ( ti_max * t_max.second < t_max_x_diff )
- {
- t_max.first = ti_max;
- t_max.second = diff;
- }
-
- if ( t_min.first > t_min.second || t_max.first < 0 )
- {
- return true;
- }
-
- return disjoint_segment_box_impl
- <
- RelativeDistance,
- SegmentPoint,
- Box,
- I + 1,
- Dimension
- >::apply(p0, p1, box, t_min, t_max);
- }
-};
-
-
-template
-<
- typename RelativeDistance,
- typename SegmentPoint,
- typename Box,
- std::size_t Dimension
->
-struct disjoint_segment_box_impl
- <
- RelativeDistance, SegmentPoint, Box, 0, Dimension
- >
-{
- static inline bool apply(SegmentPoint const& p0,
- SegmentPoint const& p1,
- Box const& box)
- {
- std::pair<RelativeDistance, RelativeDistance> t_min, t_max;
- RelativeDistance diff;
-
- compute_tmin_tmax_per_dim<0>::apply(p0, p1, box,
- t_min.first, t_max.first, diff);
-
- if ( geometry::math::equals(diff, 0) )
- {
- if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; }
- if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; }
-
- if (math::sign(t_min.first) * math::sign(t_max.first) > 0)
- {
- return true;
- }
- }
-
- if ( t_min.first > diff || t_max.first < 0 )
- {
- return true;
- }
-
- t_min.second = t_max.second = diff;
-
- return disjoint_segment_box_impl
- <
- RelativeDistance, SegmentPoint, Box, 1, Dimension
- >::apply(p0, p1, box, t_min, t_max);
- }
-};
-
-
-template
-<
- typename RelativeDistance,
- typename SegmentPoint,
- typename Box,
- std::size_t Dimension
->
-struct disjoint_segment_box_impl
- <
- RelativeDistance, SegmentPoint, Box, Dimension, Dimension
- >
-{
- template <typename RelativeDistancePair>
- static inline bool apply(SegmentPoint const&, SegmentPoint const&,
- Box const&,
- RelativeDistancePair&, RelativeDistancePair&)
- {
- return false;
- }
-};
-
-
-//=========================================================================
-
-
-template <typename Segment, typename Box>
struct disjoint_segment_box
-{
- static inline bool apply(Segment const& segment, Box const& box)
+{
+ template <typename Segment, typename Box, typename Strategy>
+ static inline bool apply(Segment const& segment, Box const& box, Strategy const& strategy)
{
- assert_dimension_equal<Segment, Box>();
-
- typedef typename util::calculation_type::geometric::binary
- <
- Segment, Box, void
- >::type relative_distance_type;
-
- typedef typename point_type<Segment>::type segment_point_type;
- segment_point_type p0, p1;
- geometry::detail::assign_point_from_index<0>(segment, p0);
- geometry::detail::assign_point_from_index<1>(segment, p1);
-
- return disjoint_segment_box_impl
- <
- relative_distance_type, segment_point_type, Box,
- 0, dimension<Box>::value
- >::apply(p0, p1, box);
+ return strategy.apply(segment, box);
}
};
-
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
-
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
@@ -284,7 +56,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<Segment, Box>
+ : detail::disjoint::disjoint_segment_box
{};
diff --git a/boost/geometry/algorithms/detail/envelope/box.hpp b/boost/geometry/algorithms/detail/envelope/box.hpp
index 3790262948..795f51392e 100644
--- a/boost/geometry/algorithms/detail/envelope/box.hpp
+++ b/boost/geometry/algorithms/detail/envelope/box.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// 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, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -97,8 +98,10 @@ struct envelope_indexed_box_on_spheroid
struct envelope_box
{
- template<typename BoxIn, typename BoxOut>
- static inline void apply(BoxIn const& box_in, BoxOut& mbr)
+ template<typename BoxIn, typename BoxOut, typename Strategy>
+ static inline void apply(BoxIn const& box_in,
+ BoxOut& mbr,
+ Strategy const&)
{
envelope_indexed_box
<
@@ -115,8 +118,10 @@ struct envelope_box
struct envelope_box_on_spheroid
{
- template <typename BoxIn, typename BoxOut>
- static inline void apply(BoxIn const& box_in, BoxOut& mbr)
+ template <typename BoxIn, typename BoxOut, typename Strategy>
+ static inline void apply(BoxIn const& box_in,
+ BoxOut& mbr,
+ Strategy const&)
{
BoxIn box_in_normalized = detail::return_normalized<BoxIn>(box_in);
diff --git a/boost/geometry/algorithms/detail/envelope/implementation.hpp b/boost/geometry/algorithms/detail/envelope/implementation.hpp
index c1dbf8e589..d549700791 100644
--- a/boost/geometry/algorithms/detail/envelope/implementation.hpp
+++ b/boost/geometry/algorithms/detail/envelope/implementation.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// 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, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, 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
@@ -45,8 +46,8 @@ namespace detail { namespace envelope
struct envelope_polygon
{
- template <typename Polygon, typename Box>
- static inline void apply(Polygon const& polygon, Box& mbr)
+ template <typename Polygon, typename Box, typename Strategy>
+ static inline void apply(Polygon const& polygon, Box& mbr, Strategy const& strategy)
{
typename ring_return_type<Polygon const>::type ext_ring
= exterior_ring(polygon);
@@ -57,12 +58,12 @@ struct envelope_polygon
envelope_multi_range
<
envelope_range
- >::apply(interior_rings(polygon), mbr);
+ >::apply(interior_rings(polygon), mbr, strategy);
}
else
{
// otherwise, consider only the exterior ring
- envelope_range::apply(ext_ring, mbr);
+ envelope_range::apply(ext_ring, mbr, strategy);
}
}
};
diff --git a/boost/geometry/algorithms/detail/envelope/interface.hpp b/boost/geometry/algorithms/detail/envelope/interface.hpp
index befe4e42db..8e9c35b395 100644
--- a/boost/geometry/algorithms/detail/envelope/interface.hpp
+++ b/boost/geometry/algorithms/detail/envelope/interface.hpp
@@ -4,10 +4,12 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// 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, 2016, 2017.
+// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
+// 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.
@@ -27,54 +29,124 @@
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/envelope.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
+#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
+#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
namespace boost { namespace geometry
{
-namespace resolve_variant
+namespace resolve_strategy
{
template <typename Geometry>
struct envelope
{
+ template <typename Box, typename Strategy>
+ static inline void apply(Geometry const& geometry,
+ Box& box,
+ Strategy const& strategy)
+ {
+ dispatch::envelope<Geometry>::apply(geometry, box, strategy);
+ }
+
template <typename Box>
- static inline void apply(Geometry const& geometry, Box& box)
+ static inline void apply(Geometry const& geometry,
+ Box& box,
+ default_strategy)
+ {
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename coordinate_type<point_type>::type coordinate_type;
+
+ typedef typename strategy::envelope::services::default_strategy
+ <
+ typename cs_tag<point_type>::type,
+ coordinate_type
+ >::type strategy_type;
+
+ dispatch::envelope<Geometry>::apply(geometry, box, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+namespace resolve_variant
+{
+
+template <typename Geometry>
+struct envelope
+{
+ template <typename Box, typename Strategy>
+ static inline void apply(Geometry const& geometry,
+ Box& box,
+ Strategy const& strategy)
{
concepts::check<Geometry const>();
concepts::check<Box>();
- dispatch::envelope<Geometry>::apply(geometry, box);
+ resolve_strategy::envelope<Geometry>::apply(geometry, box, strategy);
}
};
+
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
- template <typename Box>
+ template <typename Box, typename Strategy>
struct visitor: boost::static_visitor<void>
{
Box& m_box;
+ Strategy const& m_strategy;
- visitor(Box& box): m_box(box) {}
+ visitor(Box& box, Strategy const& strategy)
+ : m_box(box)
+ , m_strategy(strategy)
+ {}
template <typename Geometry>
void operator()(Geometry const& geometry) const
{
- envelope<Geometry>::apply(geometry, m_box);
+ envelope<Geometry>::apply(geometry, m_box, m_strategy);
}
};
- template <typename Box>
+ template <typename Box, typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- Box& box)
+ Box& box,
+ Strategy const& strategy)
{
- boost::apply_visitor(visitor<Box>(box), geometry);
+ boost::apply_visitor(visitor<Box, Strategy>(box, strategy), geometry);
}
};
} // namespace resolve_variant
+/*!
+\brief \brief_calc{envelope (with strategy)}
+\ingroup envelope
+\details \details_calc{envelope,\det_envelope}.
+\tparam Geometry \tparam_geometry
+\tparam Box \tparam_box
+\tparam Strategy \tparam_strategy{Envelope}
+\param geometry \param_geometry
+\param mbr \param_box \param_set{envelope}
+\param strategy \param_strategy{envelope}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/envelope.qbk]}
+\qbk{
+[heading Example]
+[envelope] [envelope_output]
+}
+*/
+template<typename Geometry, typename Box, typename Strategy>
+inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strategy)
+{
+ resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
+}
/*!
\brief \brief_calc{envelope}
@@ -94,7 +166,7 @@ struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template<typename Geometry, typename Box>
inline void envelope(Geometry const& geometry, Box& mbr)
{
- resolve_variant::envelope<Geometry>::apply(geometry, mbr);
+ resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
}
@@ -104,6 +176,32 @@ inline void envelope(Geometry const& geometry, Box& mbr)
\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope}
\tparam Box \tparam_box
\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{Envelope}
+\param geometry \param_geometry
+\param strategy \param_strategy{envelope}
+\return \return_calc{envelope}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/envelope.qbk]}
+\qbk{
+[heading Example]
+[return_envelope] [return_envelope_output]
+}
+*/
+template<typename Box, typename Geometry, typename Strategy>
+inline Box return_envelope(Geometry const& geometry, Strategy const& strategy)
+{
+ Box mbr;
+ resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
+ return mbr;
+}
+
+/*!
+\brief \brief_calc{envelope}
+\ingroup envelope
+\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope}
+\tparam Box \tparam_box
+\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\return \return_calc{envelope}
@@ -117,7 +215,7 @@ template<typename Box, typename Geometry>
inline Box return_envelope(Geometry const& geometry)
{
Box mbr;
- resolve_variant::envelope<Geometry>::apply(geometry, mbr);
+ resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
return mbr;
}
diff --git a/boost/geometry/algorithms/detail/envelope/linear.hpp b/boost/geometry/algorithms/detail/envelope/linear.hpp
index 49c3cf3135..09d8a76da5 100644
--- a/boost/geometry/algorithms/detail/envelope/linear.hpp
+++ b/boost/geometry/algorithms/detail/envelope/linear.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// 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, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -36,12 +37,15 @@ namespace detail { namespace envelope
struct envelope_linestring_on_spheroid
{
- template <typename Linestring, typename Box>
- static inline void apply(Linestring const& linestring, Box& mbr)
+ template <typename Linestring, typename Box, typename Strategy>
+ static inline void apply(Linestring const& linestring,
+ Box& mbr,
+ Strategy const& strategy)
{
envelope_range::apply(geometry::segments_begin(linestring),
geometry::segments_end(linestring),
- mbr);
+ mbr,
+ strategy);
}
};
@@ -65,6 +69,11 @@ struct envelope<Linestring, linestring_tag, spherical_equatorial_tag>
: detail::envelope::envelope_linestring_on_spheroid
{};
+template <typename Linestring>
+struct envelope<Linestring, linestring_tag, geographic_tag>
+ : detail::envelope::envelope_linestring_on_spheroid
+{};
+
template <typename MultiLinestring, typename CS_Tag>
struct envelope
@@ -86,6 +95,15 @@ struct envelope
>
{};
+template <typename MultiLinestring>
+struct envelope
+ <
+ MultiLinestring, multi_linestring_tag, geographic_tag
+ > : detail::envelope::envelope_multi_range_on_spheroid
+ <
+ detail::envelope::envelope_linestring_on_spheroid
+ >
+{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/envelope/multipoint.hpp b/boost/geometry/algorithms/detail/envelope/multipoint.hpp
index 210debfdba..efee4701c9 100644
--- a/boost/geometry/algorithms/detail/envelope/multipoint.hpp
+++ b/boost/geometry/algorithms/detail/envelope/multipoint.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015, Oracle and/or its affiliates.
+// Copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -226,8 +227,8 @@ private:
}
public:
- template <typename MultiPoint, typename Box>
- static inline void apply(MultiPoint const& multipoint, Box& mbr)
+ template <typename MultiPoint, typename Box, typename Strategy>
+ static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& strategy)
{
typedef typename point_type<MultiPoint>::type point_type;
typedef typename coordinate_type<MultiPoint>::type coordinate_type;
@@ -255,7 +256,7 @@ public:
return dispatch::envelope
<
typename boost::range_value<MultiPoint>::type
- >::apply(range::front(multipoint), mbr);
+ >::apply(range::front(multipoint), mbr, strategy);
}
// analyze the points and put the non-pole ones in the
@@ -329,7 +330,7 @@ public:
// compute envelope for higher coordinates
iterator_type it = boost::begin(multipoint);
- envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr);
+ envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr, strategy);
for (++it; it != boost::end(multipoint); ++it)
{
@@ -338,7 +339,7 @@ public:
strategy::compare::default_strategy,
strategy::compare::default_strategy,
2, dimension<Box>::value
- >::apply(mbr, *it);
+ >::apply(mbr, *it, strategy);
}
}
};
diff --git a/boost/geometry/algorithms/detail/envelope/point.hpp b/boost/geometry/algorithms/detail/envelope/point.hpp
index e914e7e8a0..ee0559bf5f 100644
--- a/boost/geometry/algorithms/detail/envelope/point.hpp
+++ b/boost/geometry/algorithms/detail/envelope/point.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// 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, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -58,8 +59,8 @@ struct envelope_one_point
>::apply(point, box_corner);
}
- template <typename Point, typename Box>
- static inline void apply(Point const& point, Box& mbr)
+ template <typename Point, typename Box, typename Strategy>
+ static inline void apply(Point const& point, Box& mbr, Strategy const&)
{
apply<min_corner>(point, mbr);
apply<max_corner>(point, mbr);
@@ -69,8 +70,8 @@ struct envelope_one_point
struct envelope_point_on_spheroid
{
- template<typename Point, typename Box>
- static inline void apply(Point const& point, Box& mbr)
+ template<typename Point, typename Box, typename Strategy>
+ static inline void apply(Point const& point, Box& mbr, Strategy const& strategy)
{
Point normalized_point = detail::return_normalized<Point>(point);
@@ -88,7 +89,7 @@ struct envelope_point_on_spheroid
envelope_one_point
<
2, dimension<Point>::value
- >::apply(normalized_point, mbr);
+ >::apply(normalized_point, mbr, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/envelope/range.hpp b/boost/geometry/algorithms/detail/envelope/range.hpp
index 63b518114b..b5591f61ab 100644
--- a/boost/geometry/algorithms/detail/envelope/range.hpp
+++ b/boost/geometry/algorithms/detail/envelope/range.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// 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, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, 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
@@ -51,8 +52,11 @@ namespace detail { namespace envelope
// implementation for simple ranges
struct envelope_range
{
- template <typename Iterator, typename Box>
- static inline void apply(Iterator first, Iterator last, Box& mbr)
+ template <typename Iterator, typename Box, typename Strategy>
+ static inline void apply(Iterator first,
+ Iterator last,
+ Box& mbr,
+ Strategy const& strategy)
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
@@ -63,20 +67,20 @@ struct envelope_range
if (it != last)
{
// initialize box with first element in range
- dispatch::envelope<value_type>::apply(*it, mbr);
+ dispatch::envelope<value_type>::apply(*it, mbr, strategy);
// consider now the remaining elements in the range (if any)
for (++it; it != last; ++it)
{
- dispatch::expand<Box, value_type>::apply(mbr, *it);
+ dispatch::expand<Box, value_type>::apply(mbr, *it, strategy);
}
}
}
- template <typename Range, typename Box>
- static inline void apply(Range const& range, Box& mbr)
+ template <typename Range, typename Box, typename Strategy>
+ static inline void apply(Range const& range, Box& mbr, Strategy const& strategy)
{
- return apply(boost::begin(range), boost::end(range), mbr);
+ return apply(boost::begin(range), boost::end(range), mbr, strategy);
}
};
@@ -85,8 +89,10 @@ struct envelope_range
template <typename EnvelopePolicy>
struct envelope_multi_range
{
- template <typename MultiRange, typename Box>
- static inline void apply(MultiRange const& multirange, Box& mbr)
+ template <typename MultiRange, typename Box, typename Strategy>
+ static inline void apply(MultiRange const& multirange,
+ Box& mbr,
+ Strategy const& strategy)
{
typedef typename boost::range_iterator
<
@@ -103,14 +109,14 @@ struct envelope_multi_range
if (initialized)
{
Box helper_mbr;
- EnvelopePolicy::apply(*it, helper_mbr);
+ EnvelopePolicy::apply(*it, helper_mbr, strategy);
- dispatch::expand<Box, Box>::apply(mbr, helper_mbr);
+ dispatch::expand<Box, Box>::apply(mbr, helper_mbr, strategy);
}
else
{
// compute the initial envelope
- EnvelopePolicy::apply(*it, mbr);
+ EnvelopePolicy::apply(*it, mbr, strategy);
initialized = true;
}
}
@@ -129,8 +135,10 @@ struct envelope_multi_range
template <typename EnvelopePolicy>
struct envelope_multi_range_on_spheroid
{
- template <typename MultiRange, typename Box>
- static inline void apply(MultiRange const& multirange, Box& mbr)
+ template <typename MultiRange, typename Box, typename Strategy>
+ static inline void apply(MultiRange const& multirange,
+ Box& mbr,
+ Strategy const& strategy)
{
typedef typename boost::range_iterator
<
@@ -147,7 +155,7 @@ struct envelope_multi_range_on_spheroid
if (! geometry::is_empty(*it))
{
Box helper_box;
- EnvelopePolicy::apply(*it, helper_box);
+ EnvelopePolicy::apply(*it, helper_box, strategy);
boxes.push_back(helper_box);
}
}
@@ -159,7 +167,7 @@ struct envelope_multi_range_on_spheroid
// and the MBR is simply initialized
if (! boxes.empty())
{
- envelope_range_of_boxes::apply(boxes, mbr);
+ envelope_range_of_boxes::apply(boxes, mbr, strategy);
}
else
{
diff --git a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
index 64bdb9b9cb..f61fc422de 100644
--- a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
+++ b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015, Oracle and/or its affiliates.
+// Copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -149,8 +150,10 @@ struct envelope_range_of_longitudes
template <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_range_of_boxes_by_expansion
{
- template <typename RangeOfBoxes, typename Box>
- static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr)
+ template <typename RangeOfBoxes, typename Box, typename Strategy>
+ static inline void apply(RangeOfBoxes const& range_of_boxes,
+ Box& mbr,
+ Strategy const& strategy)
{
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
@@ -196,7 +199,7 @@ struct envelope_range_of_boxes_by_expansion
min_corner,
Dimension,
DimensionCount
- >::apply(mbr, *it);
+ >::apply(mbr, *it, strategy);
detail::expand::indexed_loop
<
@@ -205,7 +208,7 @@ struct envelope_range_of_boxes_by_expansion
max_corner,
Dimension,
DimensionCount
- >::apply(mbr, *it);
+ >::apply(mbr, *it, strategy);
}
}
@@ -225,8 +228,10 @@ struct envelope_range_of_boxes
}
};
- template <typename RangeOfBoxes, typename Box>
- static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr)
+ template <typename RangeOfBoxes, typename Box, typename Strategy>
+ static inline void apply(RangeOfBoxes const& range_of_boxes,
+ Box& mbr,
+ Strategy const& strategy)
{
// boxes in the range are assumed to be normalized already
@@ -313,7 +318,7 @@ struct envelope_range_of_boxes
envelope_range_of_boxes_by_expansion
<
2, dimension<Box>::value
- >::apply(range_of_boxes, mbr);
+ >::apply(range_of_boxes, mbr, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/envelope/segment.hpp b/boost/geometry/algorithms/detail/envelope/segment.hpp
index 6186e72a3a..7631e84883 100644
--- a/boost/geometry/algorithms/detail/envelope/segment.hpp
+++ b/boost/geometry/algorithms/detail/envelope/segment.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015, 2016.
-// Modifications copyright (c) 2015-2016, 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 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
@@ -26,6 +27,7 @@
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/srs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -34,10 +36,9 @@
#include <boost/geometry/geometries/helper_geometry.hpp>
-#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/formulas/vertex_latitude.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
-#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/point.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
@@ -46,7 +47,6 @@
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
-
namespace boost { namespace geometry
{
@@ -54,63 +54,36 @@ namespace boost { namespace geometry
namespace detail { namespace envelope
{
-
-template <std::size_t Dimension, std::size_t DimensionCount>
-struct envelope_one_segment
+template <typename CalculationType, typename CS_Tag>
+struct envelope_segment_call_vertex_latitude
{
- template<typename Point, typename Box>
- static inline void apply(Point const& p1, Point const& p2, Box& mbr)
+ template <typename T1, typename T2, typename Strategy>
+ static inline CalculationType apply(T1 const& lat1,
+ T2 const& alp1,
+ Strategy const& )
{
- envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr);
- detail::expand::point_loop
- <
- strategy::compare::default_strategy,
- strategy::compare::default_strategy,
- Dimension,
- DimensionCount
- >::apply(mbr, p2);
+ return geometry::formula::vertex_latitude<CalculationType, CS_Tag>
+ ::apply(lat1, alp1);
}
};
-
-// Computes the MBR of a segment given by (lon1, lat1) and (lon2,
-// lat2), and with azimuths a1 and a2 at the two endpoints of the
-// segment.
-// It is assumed that the spherical coordinates of the segment are
-// normalized and in radians.
-// The longitudes and latitudes of the endpoints are overridden by
-// those of the box.
-class compute_mbr_of_segment
+template <typename CalculationType>
+struct envelope_segment_call_vertex_latitude<CalculationType, geographic_tag>
{
-private:
- // computes the azimuths of the segment with endpoints (lon1, lat1)
- // and (lon2, lat2)
- // radians
- template <typename CalculationType>
- static inline void azimuths(CalculationType const& lon1,
- CalculationType const& lat1,
- CalculationType const& lon2,
- CalculationType const& lat2,
- CalculationType& a1,
- CalculationType& a2)
+ template <typename T1, typename T2, typename Strategy>
+ static inline CalculationType apply(T1 const& lat1,
+ T2 const& alp1,
+ Strategy const& strategy)
{
- BOOST_GEOMETRY_ASSERT(lon1 <= lon2);
-
- CalculationType dlon = lon2 - lon1;
- CalculationType sin_dlon = sin(dlon);
- CalculationType cos_dlon = cos(dlon);
- CalculationType cos_lat1 = cos(lat1);
- CalculationType cos_lat2 = cos(lat2);
- CalculationType sin_lat1 = sin(lat1);
- CalculationType sin_lat2 = sin(lat2);
-
- a1 = atan2(sin_dlon * cos_lat2,
- cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon);
-
- a2 = atan2(-sin_dlon * cos_lat1,
- cos_lat2 * sin_lat1 - sin_lat2 * cos_lat1 * cos_dlon);
- a2 += math::pi<CalculationType>();
+ return geometry::formula::vertex_latitude<CalculationType, geographic_tag>
+ ::apply(lat1, alp1, strategy.model());
}
+};
+
+template <typename CS_Tag>
+class envelope_segment_impl
+{
+private:
// degrees or radians
template <typename CalculationType>
@@ -134,8 +107,8 @@ private:
static CalculationType const pi_half = math::half_pi<CalculationType>();
return (a1 < a2)
- ? (a1 < pi_half && pi_half < a2)
- : (a1 > pi_half && pi_half > a2);
+ ? (a1 < pi_half && pi_half < a2)
+ : (a1 > pi_half && pi_half > a2);
}
// radians or degrees
@@ -151,21 +124,13 @@ private:
return math::abs(lon1 - lon2) > constants::half_period(); // > pi
}
- // radians
- template <typename CalculationType>
- static inline CalculationType max_latitude(CalculationType const& azimuth,
- CalculationType const& latitude)
- {
- // azimuth and latitude are assumed to be in radians
- return acos( math::abs(cos(latitude) * sin(azimuth)) );
- }
-
// degrees or radians
- template <typename Units, typename CalculationType>
+ template <typename Units, typename CalculationType, typename Strategy>
static inline void compute_box_corners(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
- CalculationType& lat2)
+ CalculationType& lat2,
+ Strategy const& strategy)
{
// coordinates are assumed to be in radians
BOOST_GEOMETRY_ASSERT(lon1 <= lon2);
@@ -175,13 +140,14 @@ private:
CalculationType lon2_rad = math::as_radian<Units>(lon2);
CalculationType lat2_rad = math::as_radian<Units>(lat2);
- CalculationType a1 = 0, a2 = 0;
- azimuths(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2);
+ CalculationType a1, a2;
+ strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2);
if (lat1 > lat2)
{
std::swap(lat1, lat2);
std::swap(lat1_rad, lat2_rad);
+ std::swap(a1, a2);
}
if (math::equals(a1, a2))
@@ -192,12 +158,16 @@ private:
if (contains_pi_half(a1, a2))
{
+ CalculationType p_max = envelope_segment_call_vertex_latitude
+ <CalculationType, CS_Tag>::apply(lat1_rad, a1, strategy);
+
CalculationType const mid_lat = lat1 + lat2;
if (mid_lat < 0)
{
// update using min latitude
- CalculationType const lat_min_rad = -max_latitude(a1, lat1_rad);
- CalculationType const lat_min = math::from_radian<Units>(lat_min_rad);
+ CalculationType const lat_min_rad = -p_max;
+ CalculationType const lat_min
+ = math::from_radian<Units>(lat_min_rad);
if (lat1 > lat_min)
{
@@ -207,8 +177,9 @@ private:
else if (mid_lat > 0)
{
// update using max latitude
- CalculationType const lat_max_rad = max_latitude(a1, lat1_rad);
- CalculationType const lat_max = math::from_radian<Units>(lat_max_rad);
+ CalculationType const lat_max_rad = p_max;
+ CalculationType const lat_max
+ = math::from_radian<Units>(lat_max_rad);
if (lat2 < lat_max)
{
@@ -218,11 +189,12 @@ private:
}
}
- template <typename Units, typename CalculationType>
+ template <typename Units, typename CalculationType, typename Strategy>
static inline void apply(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
- CalculationType& lat2)
+ CalculationType& lat2,
+ Strategy const& strategy)
{
typedef math::detail::constants_on_spheroid
<
@@ -278,16 +250,22 @@ private:
swap(lon1, lat1, lon2, lat2);
}
- compute_box_corners<Units>(lon1, lat1, lon2, lat2);
+ compute_box_corners<Units>(lon1, lat1, lon2, lat2, strategy);
}
public:
- template <typename Units, typename CalculationType, typename Box>
+ template <
+ typename Units,
+ typename CalculationType,
+ typename Box,
+ typename Strategy
+ >
static inline void apply(CalculationType lon1,
CalculationType lat1,
CalculationType lon2,
CalculationType lat2,
- Box& mbr)
+ Box& mbr,
+ Strategy const& strategy)
{
typedef typename coordinate_type<Box>::type box_coordinate_type;
@@ -298,7 +276,7 @@ public:
helper_box_type radian_mbr;
- apply<Units>(lon1, lat1, lon2, lat2);
+ apply<Units>(lon1, lat1, lon2, lat2, strategy);
geometry::set
<
@@ -324,29 +302,42 @@ public:
}
};
+template <std::size_t Dimension, std::size_t DimensionCount>
+struct envelope_one_segment
+{
+ template<typename Point, typename Box, typename Strategy>
+ static inline void apply(Point const& p1,
+ Point const& p2,
+ Box& mbr,
+ Strategy const& strategy)
+ {
+ envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr, strategy);
+ detail::expand::point_loop
+ <
+ strategy::compare::default_strategy,
+ strategy::compare::default_strategy,
+ Dimension,
+ DimensionCount
+ >::apply(mbr, p2, strategy);
+ }
+};
+
template <std::size_t DimensionCount>
-struct envelope_segment_on_sphere
+struct envelope_segment
{
- template <typename Point, typename Box>
- static inline void apply(Point const& p1, Point const& p2, Box& mbr)
+ template <typename Point, typename Box, typename Strategy>
+ static inline void apply(Point const& p1,
+ Point const& p2,
+ Box& mbr,
+ Strategy const& strategy)
{
// first compute the envelope range for the first two coordinates
- Point p1_normalized = detail::return_normalized<Point>(p1);
- Point p2_normalized = detail::return_normalized<Point>(p2);
-
- typedef typename coordinate_system<Point>::type::units units_type;
-
- compute_mbr_of_segment::template apply<units_type>(
- geometry::get<0>(p1_normalized),
- geometry::get<1>(p1_normalized),
- geometry::get<0>(p2_normalized),
- geometry::get<1>(p2_normalized),
- mbr);
+ strategy.apply(p1, p2, mbr);
// now compute the envelope range for coordinates of
// dimension 2 and higher
- envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr);
+ envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr, strategy);
}
template <typename Segment, typename Box>
@@ -359,21 +350,6 @@ struct envelope_segment_on_sphere
}
};
-
-
-template <std::size_t DimensionCount, typename CS_Tag>
-struct envelope_segment
- : envelope_one_segment<0, DimensionCount>
-{};
-
-
-template <std::size_t DimensionCount>
-struct envelope_segment<DimensionCount, spherical_equatorial_tag>
- : envelope_segment_on_sphere<DimensionCount>
-{};
-
-
-
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
@@ -383,23 +359,24 @@ namespace dispatch
{
-template <typename Segment, typename CS_Tag>
-struct envelope<Segment, segment_tag, CS_Tag>
+template <typename Segment>
+struct envelope<Segment, segment_tag>
{
- template <typename Box>
- static inline void apply(Segment const& segment, Box& mbr)
+ template <typename Box, typename Strategy>
+ static inline void apply(Segment const& segment,
+ Box& mbr,
+ Strategy const& strategy)
{
typename point_type<Segment>::type p[2];
detail::assign_point_from_index<0>(segment, p[0]);
detail::assign_point_from_index<1>(segment, p[1]);
detail::envelope::envelope_segment
<
- dimension<Segment>::value, CS_Tag
- >::apply(p[0], p[1], mbr);
+ dimension<Segment>::value
+ >::apply(p[0], p[1], mbr, strategy);
}
};
-
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
index eab73ea680..9625f18426 100644
--- a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
+++ b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
@@ -3,7 +3,12 @@
// 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.
-// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2017 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.
@@ -20,6 +25,7 @@
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/interior_rings.hpp>
@@ -32,21 +38,37 @@
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/range.hpp>
+#include <boost/geometry/views/detail/normalized_view.hpp>
+
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
+#include <boost/geometry/strategies/spherical/ssf.hpp>
+
namespace boost { namespace geometry
{
+// TODO: dispatch only by SideStrategy instead of Geometry/CSTag?
+
// Since these vectors (though ray would be a better name) are used in the
// implementation of equals() for Areal geometries the internal representation
-// should be consistent with the default side strategy for CS because currently
-// it's used in other relops.
-
-template <
+// should be consistent with the side strategy.
+template
+<
typename T,
typename Geometry,
+ typename SideStrategy,
typename CSTag = typename cs_tag<Geometry>::type
>
struct collected_vector
+ : nyi::not_implemented_tag
+{};
+
+// compatible with side_by_triangle cartesian strategy
+template <typename T, typename Geometry, typename CT, typename CSTag>
+struct collected_vector
+ <
+ T, Geometry, strategy::side::side_by_triangle<CT>, CSTag
+ >
{
typedef T type;
@@ -136,8 +158,13 @@ private:
//T dx_0, dy_0;
};
-template <typename T, typename Geometry>
-struct collected_vector<T, Geometry, spherical_equatorial_tag>
+// Compatible with spherical_side_formula which currently
+// is the default spherical and geographical strategy
+template <typename T, typename Geometry, typename CT, typename CSTag>
+struct collected_vector
+ <
+ T, Geometry, strategy::side::spherical_side_formula<CT>, CSTag
+ >
{
typedef T type;
@@ -232,11 +259,27 @@ private:
vector_type next; // used for collinearity check
};
-template <typename T, typename Geometry>
-struct collected_vector<T, Geometry, spherical_polar_tag>
- : public collected_vector<T, Geometry, spherical_equatorial_tag>
+// Specialization for spherical polar
+template <typename T, typename Geometry, typename CT>
+struct collected_vector
+ <
+ T, Geometry,
+ strategy::side::spherical_side_formula<CT>,
+ spherical_polar_tag
+ >
+ : public collected_vector
+ <
+ T, Geometry,
+ strategy::side::spherical_side_formula<CT>,
+ spherical_equatorial_tag
+ >
{
- typedef collected_vector<T, Geometry, spherical_equatorial_tag> base_type;
+ typedef collected_vector
+ <
+ T, Geometry,
+ strategy::side::spherical_side_formula<CT>,
+ spherical_equatorial_tag
+ > base_type;
collected_vector() {}
@@ -265,24 +308,6 @@ private:
}
};
-// This is consistent with the currently used default geographic side
-// and intersection strategies. Spherical strategies are used by default.
-// When default strategies are changed in the future this specialization
-// should be changed too.
-template <typename T, typename Geometry>
-struct collected_vector<T, Geometry, geographic_tag>
- : public collected_vector<T, Geometry, spherical_equatorial_tag>
-{
- typedef collected_vector<T, Geometry, spherical_equatorial_tag> base_type;
-
- collected_vector() {}
-
- template <typename Point>
- collected_vector(Point const& p1, Point const& p2)
- : base_type(p1, p2)
- {}
-};
-
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace collect_vectors
@@ -297,6 +322,18 @@ struct range_collect_vectors
static inline void apply(Collection& collection, Range const& range)
{
+ typedef geometry::detail::normalized_view
+ <
+ Range const
+ > normalized_range_type;
+
+ apply_impl(collection, normalized_range_type(range));
+ }
+
+private:
+ template <typename NormalizedRange>
+ static inline void apply_impl(Collection& collection, NormalizedRange const& range)
+ {
if (boost::size(range) < 2)
{
return;
@@ -305,7 +342,7 @@ struct range_collect_vectors
typedef typename boost::range_size<Collection>::type collection_size_t;
collection_size_t c_old_size = boost::size(collection);
- typedef typename boost::range_iterator<Range const>::type iterator;
+ typedef typename boost::range_iterator<NormalizedRange const>::type iterator;
bool is_first = true;
iterator it = boost::begin(range);
diff --git a/boost/geometry/algorithms/detail/expand/box.hpp b/boost/geometry/algorithms/detail/expand/box.hpp
index 4c89e6f1d4..3edb23f5ae 100644
--- a/boost/geometry/algorithms/detail/expand/box.hpp
+++ b/boost/geometry/algorithms/detail/expand/box.hpp
@@ -5,9 +5,10 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
-// 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, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -44,16 +45,18 @@ namespace detail { namespace expand
struct box_on_spheroid
{
- template <typename BoxOut, typename BoxIn>
- static inline void apply(BoxOut& box_out, BoxIn const& box_in)
+ template <typename BoxOut, typename BoxIn, typename Strategy>
+ static inline void apply(BoxOut& box_out,
+ BoxIn const& box_in,
+ Strategy const& strategy)
{
// normalize both boxes and convert box-in to be of type of box-out
BoxOut mbrs[2];
- detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0]);
- detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1]);
+ detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0], strategy);
+ detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1], strategy);
// compute the envelope of the two boxes
- detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out);
+ detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/expand/indexed.hpp b/boost/geometry/algorithms/detail/expand/indexed.hpp
index bdd6eb4506..28cf0e2e4f 100644
--- a/boost/geometry/algorithms/detail/expand/indexed.hpp
+++ b/boost/geometry/algorithms/detail/expand/indexed.hpp
@@ -5,9 +5,10 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
-// 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, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, 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
@@ -49,8 +50,8 @@ template
>
struct indexed_loop
{
- template <typename Box, typename Geometry>
- static inline void apply(Box& box, Geometry const& source)
+ template <typename Box, typename Geometry, typename Strategy>
+ static inline void apply(Box& box, Geometry const& source, Strategy const& strategy)
{
typedef typename strategy::compare::detail::select_strategy
<
@@ -87,7 +88,7 @@ struct indexed_loop
<
StrategyLess, StrategyGreater,
Index, Dimension + 1, DimensionCount
- >::apply(box, source);
+ >::apply(box, source, strategy);
}
};
@@ -103,8 +104,8 @@ struct indexed_loop
Index, DimensionCount, DimensionCount
>
{
- template <typename Box, typename Geometry>
- static inline void apply(Box&, Geometry const&) {}
+ template <typename Box, typename Geometry, typename Strategy>
+ static inline void apply(Box&, Geometry const&, Strategy const&) {}
};
@@ -117,20 +118,22 @@ template
>
struct expand_indexed
{
- template <typename Box, typename Geometry>
- static inline void apply(Box& box, Geometry const& geometry)
+ template <typename Box, typename Geometry, typename Strategy>
+ static inline void apply(Box& box,
+ Geometry const& geometry,
+ Strategy const& strategy)
{
indexed_loop
<
StrategyLess, StrategyGreater,
0, Dimension, DimensionCount
- >::apply(box, geometry);
+ >::apply(box, geometry, strategy);
indexed_loop
<
StrategyLess, StrategyGreater,
1, Dimension, DimensionCount
- >::apply(box, geometry);
+ >::apply(box, geometry, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/expand/interface.hpp b/boost/geometry/algorithms/detail/expand/interface.hpp
index 140754af4e..5aacd8e72a 100644
--- a/boost/geometry/algorithms/detail/expand/interface.hpp
+++ b/boost/geometry/algorithms/detail/expand/interface.hpp
@@ -5,9 +5,10 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
-// 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, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, 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
@@ -28,10 +29,50 @@
#include <boost/geometry/algorithms/dispatch/expand.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+
+#include <boost/geometry/strategies/envelope.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
+#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
+#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
namespace boost { namespace geometry
{
+namespace resolve_strategy
+{
+
+template <typename Geometry>
+struct expand
+{
+ template <typename Box, typename Strategy>
+ static inline void apply(Box& box,
+ Geometry const& geometry,
+ Strategy const& strategy)
+ {
+ dispatch::expand<Box, Geometry>::apply(box, geometry, strategy);
+ }
+
+ template <typename Box>
+ static inline void apply(Box& box,
+ Geometry const& geometry,
+ default_strategy)
+ {
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename coordinate_type<point_type>::type coordinate_type;
+
+ typedef typename strategy::envelope::services::default_strategy
+ <
+ typename cs_tag<point_type>::type,
+ coordinate_type
+ >::type strategy_type;
+
+ dispatch::expand<Box, Geometry>::apply(box, geometry, strategy_type());
+ }
+};
+
+} //namespace resolve_strategy
+
namespace resolve_variant
{
@@ -39,40 +80,48 @@ namespace resolve_variant
template <typename Geometry>
struct expand
{
- template <typename Box>
- static inline void apply(Box& box, Geometry const& geometry)
+ template <typename Box, typename Strategy>
+ static inline void apply(Box& box,
+ Geometry const& geometry,
+ Strategy const& strategy)
{
concepts::check<Box>();
concepts::check<Geometry const>();
concepts::check_concepts_and_equal_dimensions<Box, Geometry const>();
- dispatch::expand<Box, Geometry>::apply(box, geometry);
+ resolve_strategy::expand<Geometry>::apply(box, geometry, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
- template <typename Box>
+ template <typename Box, typename Strategy>
struct visitor: boost::static_visitor<void>
{
Box& m_box;
+ Strategy const& m_strategy;
- visitor(Box& box) : m_box(box) {}
+ visitor(Box& box, Strategy const& strategy)
+ : m_box(box)
+ , m_strategy(strategy)
+ {}
template <typename Geometry>
void operator()(Geometry const& geometry) const
{
- return expand<Geometry>::apply(m_box, geometry);
+ return expand<Geometry>::apply(m_box, geometry, m_strategy);
}
};
- template <class Box>
+ template <class Box, typename Strategy>
static inline void
apply(Box& box,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Box>(box), geometry);
+ return boost::apply_visitor(visitor<Box, Strategy>(box, strategy),
+ geometry);
}
};
@@ -106,21 +155,43 @@ inline void expand(Box& box, Geometry const& geometry,
}
***/
+/*!
+\brief Expands (with strategy)
+\ingroup expand
+\tparam Box type of the box
+\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{expand}
+\param box box to be expanded using another geometry, mutable
+\param geometry \param_geometry geometry which envelope (bounding box)
+\param strategy \param_strategy{expand}
+will be added to the box
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/expand.qbk]}
+ */
+template <typename Box, typename Geometry, typename Strategy>
+inline void expand(Box& box, Geometry const& geometry, Strategy const& strategy)
+{
+
+ resolve_variant::expand<Geometry>::apply(box, geometry, strategy);
+}
/*!
-\brief Expands a box using the bounding box (envelope) of another geometry (box, point)
+\brief Expands a box using the bounding box (envelope) of another geometry
+(box, point)
\ingroup expand
\tparam Box type of the box
\tparam Geometry \tparam_geometry
\param box box to be expanded using another geometry, mutable
-\param geometry \param_geometry geometry which envelope (bounding box) will be added to the box
+\param geometry \param_geometry geometry which envelope (bounding box) will be
+added to the box
\qbk{[include reference/algorithms/expand.qbk]}
*/
template <typename Box, typename Geometry>
inline void expand(Box& box, Geometry const& geometry)
{
- resolve_variant::expand<Geometry>::apply(box, geometry);
+ resolve_variant::expand<Geometry>::apply(box, geometry, default_strategy());
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/expand/point.hpp b/boost/geometry/algorithms/detail/expand/point.hpp
index 56b7f1c738..f0cbd1db02 100644
--- a/boost/geometry/algorithms/detail/expand/point.hpp
+++ b/boost/geometry/algorithms/detail/expand/point.hpp
@@ -5,9 +5,10 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
-// 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, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, 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
@@ -59,8 +60,8 @@ template
>
struct point_loop
{
- template <typename Box, typename Point>
- static inline void apply(Box& box, Point const& source)
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box& box, Point const& source, Strategy const& strategy)
{
typedef typename strategy::compare::detail::select_strategy
<
@@ -95,22 +96,24 @@ struct point_loop
point_loop
<
StrategyLess, StrategyGreater, Dimension + 1, DimensionCount
- >::apply(box, source);
+ >::apply(box, source, strategy);
}
};
template
<
- typename StrategyLess, typename StrategyGreater, std::size_t DimensionCount
+ typename StrategyLess,
+ typename StrategyGreater,
+ std::size_t DimensionCount
>
struct point_loop
<
StrategyLess, StrategyGreater, DimensionCount, DimensionCount
>
{
- template <typename Box, typename Point>
- static inline void apply(Box&, Point const&) {}
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box&, Point const&, Strategy const&) {}
};
@@ -123,8 +126,10 @@ template
>
struct point_loop_on_spheroid
{
- template <typename Box, typename Point>
- static inline void apply(Box& box, Point const& point)
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box& box,
+ Point const& point,
+ Strategy const& strategy)
{
typedef typename point_type<Box>::type box_point_type;
typedef typename coordinate_type<Box>::type box_coordinate_type;
@@ -224,7 +229,7 @@ struct point_loop_on_spheroid
point_loop
<
StrategyLess, StrategyGreater, 2, DimensionCount
- >::apply(box, point);
+ >::apply(box, point, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/expand/segment.hpp b/boost/geometry/algorithms/detail/expand/segment.hpp
index 041c1e175f..0570e944d4 100644
--- a/boost/geometry/algorithms/detail/expand/segment.hpp
+++ b/boost/geometry/algorithms/detail/expand/segment.hpp
@@ -5,9 +5,10 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
-// 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, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -39,25 +40,29 @@ namespace boost { namespace geometry
namespace detail { namespace expand
{
-
-struct segment_on_sphere
+struct segment
{
- template <typename Box, typename Segment>
- static inline void apply(Box& box, Segment const& segment)
+ template <typename Box, typename Segment, typename Strategy>
+ static inline void apply(Box& box,
+ Segment const& segment,
+ Strategy const& strategy)
{
Box mbrs[2];
// compute the envelope of the segment
- detail::envelope::envelope_segment_on_sphere
+ typename point_type<Segment>::type p[2];
+ detail::assign_point_from_index<0>(segment, p[0]);
+ detail::assign_point_from_index<1>(segment, p[1]);
+ detail::envelope::envelope_segment
<
dimension<Segment>::value
- >::apply(segment, mbrs[0]);
+ >::apply(p[0], p[1], mbrs[0], strategy);
// normalize the box
- detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1]);
+ detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1], strategy);
// compute the envelope of the two boxes
- detail::envelope::envelope_range_of_boxes::apply(mbrs, box);
+ detail::envelope::envelope_range_of_boxes::apply(mbrs, box, strategy);
}
};
@@ -69,7 +74,6 @@ struct segment_on_sphere
namespace dispatch
{
-
template
<
typename Box, typename Segment,
@@ -103,13 +107,27 @@ struct expand
StrategyLess, StrategyGreater,
box_tag, segment_tag,
spherical_equatorial_tag, spherical_equatorial_tag
- > : detail::expand::segment_on_sphere
+ > : detail::expand::segment
{};
+template
+<
+ typename Box, typename Segment,
+ typename StrategyLess, typename StrategyGreater
+>
+struct expand
+ <
+ Box, Segment,
+ StrategyLess, StrategyGreater,
+ box_tag, segment_tag,
+ geographic_tag, geographic_tag
+ > : detail::expand::segment
+{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
+
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
diff --git a/boost/geometry/algorithms/detail/has_self_intersections.hpp b/boost/geometry/algorithms/detail/has_self_intersections.hpp
index 24746ac627..9a388a4d80 100644
--- a/boost/geometry/algorithms/detail/has_self_intersections.hpp
+++ b/boost/geometry/algorithms/detail/has_self_intersections.hpp
@@ -1,6 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2011-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.
+// 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
@@ -12,6 +17,8 @@
#include <deque>
#include <boost/range.hpp>
+#include <boost/throw_exception.hpp>
+
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
@@ -59,8 +66,9 @@ namespace detail { namespace overlay
{
-template <typename Geometry, typename RobustPolicy>
+template <typename Geometry, typename Strategy, typename RobustPolicy>
inline bool has_self_intersections(Geometry const& geometry,
+ Strategy const& strategy,
RobustPolicy const& robust_policy,
bool throw_on_self_intersection = true)
{
@@ -73,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, robust_policy, turns, policy);
+ geometry::self_turns<detail::overlay::assign_null_policy>(geometry, strategy, robust_policy, turns, policy);
#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
bool first = true;
@@ -113,7 +121,7 @@ inline bool has_self_intersections(Geometry const& geometry,
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
if (throw_on_self_intersection)
{
- throw overlay_invalid_input_exception();
+ BOOST_THROW_EXCEPTION(overlay_invalid_input_exception());
}
#endif
return true;
@@ -132,11 +140,16 @@ inline bool has_self_intersections(Geometry const& geometry,
typedef typename geometry::rescale_policy_type<point_type>::type
rescale_policy_type;
+ typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >::type strategy;
+
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry);
- return has_self_intersections(geometry, robust_policy,
- throw_on_self_intersection);
+ return has_self_intersections(geometry, strategy, robust_policy,
+ throw_on_self_intersection);
}
diff --git a/boost/geometry/algorithms/detail/intersection/interface.hpp b/boost/geometry/algorithms/detail/intersection/interface.hpp
index e0955de3d8..0efc9731b5 100644
--- a/boost/geometry/algorithms/detail/intersection/interface.hpp
+++ b/boost/geometry/algorithms/detail/intersection/interface.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
@@ -15,12 +15,14 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP
-// TODO: those headers probably may be removed
-#include <boost/geometry/core/coordinate_dimension.hpp>
-#include <boost/geometry/algorithms/intersects.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
@@ -51,10 +53,11 @@ struct intersection
typedef typename boost::range_value<GeometryOut>::type OneOut;
intersection_insert
- <
- Geometry1, Geometry2, OneOut,
- overlay_intersection
- >::apply(geometry1, geometry2, robust_policy, range::back_inserter(geometry_out), strategy);
+ <
+ Geometry1, Geometry2, OneOut,
+ overlay_intersection
+ >::apply(geometry1, geometry2, robust_policy,
+ range::back_inserter(geometry_out), strategy);
return true;
}
@@ -84,11 +87,12 @@ struct intersection
GeometryOut& out,
Strategy const& strategy)
{
- return intersection<
- Geometry2, Geometry1,
- Tag2, Tag1,
- false
- >::apply(g2, g1, robust_policy, out, strategy);
+ return intersection
+ <
+ Geometry2, Geometry1,
+ Tag2, Tag1,
+ false
+ >::apply(g2, g1, robust_policy, out, strategy);
}
};
@@ -96,47 +100,93 @@ struct intersection
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
-
+
+namespace resolve_strategy {
+
+struct intersection
+{
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename GeometryOut,
+ typename Strategy
+ >
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ GeometryOut & geometry_out,
+ Strategy const& strategy)
+ {
+ return dispatch::intersection
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, robust_policy, geometry_out,
+ strategy);
+ }
+
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename GeometryOut
+ >
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ GeometryOut & geometry_out,
+ default_strategy)
+ {
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry1, Geometry2
+ >::type strategy_type;
+
+ return dispatch::intersection
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, robust_policy, geometry_out,
+ strategy_type());
+ }
+};
+
+} // resolve_strategy
+
+
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2>
struct intersection
{
- template <typename GeometryOut>
- static inline bool
- apply(
- const Geometry1& geometry1,
- const Geometry2& geometry2,
- GeometryOut& geometry_out)
+ template <typename GeometryOut, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
typedef typename geometry::rescale_overlay_policy_type
- <
- Geometry1,
- Geometry2
- >::type rescale_policy_type;
+ <
+ Geometry1,
+ Geometry2
+ >::type rescale_policy_type;
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry1,
geometry2);
- typedef intersection_strategies
- <
- typename cs_tag<Geometry1>::type,
- Geometry1,
- Geometry2,
- typename geometry::point_type<Geometry1>::type,
- rescale_policy_type
- > strategy;
-
- return dispatch::intersection
- <
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, robust_policy, geometry_out, strategy());
+ return resolve_strategy::intersection::apply(geometry1,
+ geometry2,
+ robust_policy,
+ geometry_out,
+ strategy);
}
};
@@ -144,40 +194,43 @@ struct intersection
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
- template <typename GeometryOut>
+ template <typename GeometryOut, typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry2 const& m_geometry2;
GeometryOut& m_geometry_out;
+ Strategy const& m_strategy;
visitor(Geometry2 const& geometry2,
- GeometryOut& geometry_out)
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
: m_geometry2(geometry2)
, m_geometry_out(geometry_out)
+ , m_strategy(strategy)
{}
template <typename Geometry1>
- result_type operator()(Geometry1 const& geometry1) const
+ bool operator()(Geometry1 const& geometry1) const
{
return intersection
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- GeometryOut
- >
- (geometry1, m_geometry2, m_geometry_out);
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, m_geometry2, m_geometry_out, m_strategy);
}
};
- template <typename GeometryOut>
+ template <typename GeometryOut, typename Strategy>
static inline bool
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
- GeometryOut& geometry_out)
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<GeometryOut>(geometry2, geometry_out), geometry1);
+ return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry2,
+ geometry_out,
+ strategy),
+ geometry1);
}
};
@@ -185,40 +238,43 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
- template <typename GeometryOut>
+ template <typename GeometryOut, typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry1 const& m_geometry1;
GeometryOut& m_geometry_out;
+ Strategy const& m_strategy;
visitor(Geometry1 const& geometry1,
- GeometryOut& geometry_out)
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
: m_geometry1(geometry1)
, m_geometry_out(geometry_out)
+ , m_strategy(strategy)
{}
template <typename Geometry2>
- result_type operator()(Geometry2 const& geometry2) const
+ bool operator()(Geometry2 const& geometry2) const
{
return intersection
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- GeometryOut
- >
- (m_geometry1, geometry2, m_geometry_out);
+ <
+ Geometry1,
+ Geometry2
+ >::apply(m_geometry1, geometry2, m_geometry_out, m_strategy);
}
};
- template <typename GeometryOut>
+ template <typename GeometryOut, typename Strategy>
static inline bool
apply(Geometry1 const& geometry1,
- const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
- GeometryOut& geometry_out)
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<GeometryOut>(geometry1, geometry_out), geometry2);
+ return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry1,
+ geometry_out,
+ strategy),
+ geometry2);
}
};
@@ -226,38 +282,39 @@ struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
- template <typename GeometryOut>
+ template <typename GeometryOut, typename Strategy>
struct visitor: static_visitor<bool>
{
GeometryOut& m_geometry_out;
+ Strategy const& m_strategy;
- visitor(GeometryOut& geometry_out)
+ visitor(GeometryOut& geometry_out, Strategy const& strategy)
: m_geometry_out(geometry_out)
+ , m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
- result_type operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
{
return intersection
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- GeometryOut
- >
- (geometry1, geometry2, m_geometry_out);
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, m_geometry_out, m_strategy);
}
};
- template <typename GeometryOut>
+ template <typename GeometryOut, typename Strategy>
static inline bool
- apply(const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
- const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2,
- GeometryOut& geometry_out)
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<GeometryOut>(geometry_out), geometry1, geometry2);
+ return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry_out,
+ strategy),
+ geometry1, geometry2);
}
};
@@ -272,32 +329,66 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIAN
\tparam Geometry2 \tparam_geometry
\tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which
the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)
+\tparam Strategy \tparam_strategy{Intersection}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param geometry_out The output geometry, either a multi_point, multi_polygon,
multi_linestring, or a box (for intersection of two boxes)
+\param strategy \param_strategy{intersection}
+\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/intersection.qbk]}
*/
template
<
typename Geometry1,
typename Geometry2,
- typename GeometryOut
+ typename GeometryOut,
+ typename Strategy
>
inline bool intersection(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- GeometryOut& geometry_out)
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
{
return resolve_variant::intersection
<
- Geometry1,
- Geometry2
- >::template apply
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, geometry_out, strategy);
+}
+
+
+/*!
+\brief \brief_calc2{intersection}
+\ingroup intersection
+\details \details_calc2{intersection, spatial set theoretic intersection}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which
+ the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param geometry_out The output geometry, either a multi_point, multi_polygon,
+ multi_linestring, or a box (for intersection of two boxes)
+
+\qbk{[include reference/algorithms/intersection.qbk]}
+*/
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename GeometryOut
+>
+inline bool intersection(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out)
+{
+ return resolve_variant::intersection
<
- GeometryOut
- >
- (geometry1, geometry2, geometry_out);
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, geometry_out, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/is_simple/always_simple.hpp b/boost/geometry/algorithms/detail/is_simple/always_simple.hpp
index 91e2ef76bd..5cec5e1924 100644
--- a/boost/geometry/algorithms/detail/is_simple/always_simple.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/always_simple.hpp
@@ -1,8 +1,9 @@
// 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 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
@@ -27,7 +28,8 @@ namespace detail { namespace is_simple
template <typename Geometry>
struct always_simple
{
- static inline bool apply(Geometry const&)
+ template <typename Strategy>
+ static inline bool apply(Geometry const&, Strategy const&)
{
return true;
}
diff --git a/boost/geometry/algorithms/detail/is_simple/areal.hpp b/boost/geometry/algorithms/detail/is_simple/areal.hpp
index a2322e4831..d4d6db9bce 100644
--- a/boost/geometry/algorithms/detail/is_simple/areal.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/areal.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
@@ -37,6 +38,12 @@ namespace detail { namespace is_simple
template <typename Ring>
struct is_simple_ring
{
+ template <typename Strategy>
+ static inline bool apply(Ring const& ring, Strategy const&)
+ {
+ return apply(ring);
+ }
+
static inline bool apply(Ring const& ring)
{
simplicity_failure_policy policy;
@@ -69,6 +76,12 @@ private:
}
public:
+ template <typename Strategy>
+ static inline bool apply(Polygon const& polygon, Strategy const&)
+ {
+ return apply(polygon);
+ }
+
static inline bool apply(Polygon const& polygon)
{
return
@@ -119,7 +132,8 @@ struct is_simple<Polygon, polygon_tag>
template <typename MultiPolygon>
struct is_simple<MultiPolygon, multi_polygon_tag>
{
- static inline bool apply(MultiPolygon const& multipolygon)
+ template <typename Strategy>
+ static inline bool apply(MultiPolygon const& multipolygon, Strategy const&)
{
return
detail::check_iterator_range
diff --git a/boost/geometry/algorithms/detail/is_simple/interface.hpp b/boost/geometry/algorithms/detail/is_simple/interface.hpp
index 6d425232b0..af0127dc75 100644
--- a/boost/geometry/algorithms/detail/is_simple/interface.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/interface.hpp
@@ -1,8 +1,9 @@
// 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 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
@@ -17,46 +18,106 @@
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/dispatch/is_simple.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
namespace boost { namespace geometry
{
+namespace resolve_strategy
+{
+
+struct is_simple
+{
+ template <typename Geometry, typename Strategy>
+ static inline bool apply(Geometry const& geometry,
+ Strategy const& strategy)
+ {
+ return dispatch::is_simple<Geometry>::apply(geometry, strategy);
+ }
+
+ template <typename Geometry>
+ static inline bool apply(Geometry const& geometry,
+ default_strategy)
+ {
+ // NOTE: Currently the strategy is only used for Linear geometries
+ typedef typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >::type strategy_type;
+
+ return dispatch::is_simple<Geometry>::apply(geometry, strategy_type());
+ }
+};
-namespace resolve_variant {
+} // namespace resolve_strategy
+
+namespace resolve_variant
+{
template <typename Geometry>
struct is_simple
{
- static inline bool apply(Geometry const& geometry)
+ template <typename Strategy>
+ static inline bool apply(Geometry const& geometry, Strategy const& strategy)
{
concepts::check<Geometry const>();
- return dispatch::is_simple<Geometry>::apply(geometry);
+
+ return resolve_strategy::is_simple::apply(geometry, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct is_simple<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_simple<Geometry>::apply(geometry);
+ return is_simple<Geometry>::apply(geometry, m_strategy);
}
};
+ template <typename Strategy>
static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(), geometry);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
}
};
} // namespace resolve_variant
+/*!
+\brief \brief_check{is simple}
+\ingroup is_simple
+\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{Is_simple}
+\param geometry \param_geometry
+\param strategy \param_strategy{is_simple}
+\return \return_check{is simple}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/is_simple.qbk]}
+*/
+template <typename Geometry, typename Strategy>
+inline bool is_simple(Geometry const& geometry, Strategy const& strategy)
+{
+ return resolve_variant::is_simple<Geometry>::apply(geometry, strategy);
+}
+
/*!
\brief \brief_check{is simple}
@@ -70,7 +131,7 @@ struct is_simple<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline bool is_simple(Geometry const& geometry)
{
- return resolve_variant::is_simple<Geometry>::apply(geometry);
+ return resolve_variant::is_simple<Geometry>::apply(geometry, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/is_simple/linear.hpp b/boost/geometry/algorithms/detail/is_simple/linear.hpp
index 16d7b3a803..52b9d9d1c8 100644
--- a/boost/geometry/algorithms/detail/is_simple/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/linear.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
@@ -48,6 +49,8 @@
#include <boost/geometry/algorithms/dispatch/is_simple.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+
namespace boost { namespace geometry
{
@@ -186,8 +189,8 @@ private:
};
-template <typename Linear>
-inline bool has_self_intersections(Linear const& linear)
+template <typename Linear, typename Strategy>
+inline bool has_self_intersections(Linear const& linear, Strategy const& strategy)
{
typedef typename point_type<Linear>::type point_type;
@@ -218,6 +221,7 @@ inline bool has_self_intersections(Linear const& linear)
<
turn_policy
>::apply(linear,
+ strategy,
detail::no_rescale_policy(),
turns,
interrupt_policy);
@@ -243,8 +247,19 @@ struct is_simple_linestring
&& ! detail::is_valid::has_spikes
<
Linestring, closed
- >::apply(linestring, policy)
- && ! (CheckSelfIntersections && has_self_intersections(linestring));
+ >::apply(linestring, policy);
+ }
+};
+
+template <typename Linestring>
+struct is_simple_linestring<Linestring, true>
+{
+ template <typename Strategy>
+ static inline bool apply(Linestring const& linestring,
+ Strategy const& strategy)
+ {
+ return is_simple_linestring<Linestring, false>::apply(linestring)
+ && ! has_self_intersections(linestring, strategy);
}
};
@@ -252,7 +267,9 @@ struct is_simple_linestring
template <typename MultiLinestring>
struct is_simple_multilinestring
{
- static inline bool apply(MultiLinestring const& multilinestring)
+ template <typename Strategy>
+ static inline bool apply(MultiLinestring const& multilinestring,
+ Strategy const& strategy)
{
// check each of the linestrings for simplicity
// but do not compute self-intersections yet; these will be
@@ -272,7 +289,7 @@ struct is_simple_multilinestring
return false;
}
- return ! has_self_intersections(multilinestring);
+ return ! has_self_intersections(multilinestring, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp b/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
index f9f43d1cdb..61f0bc9130 100644
--- a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/multipoint.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
@@ -38,7 +39,8 @@ namespace detail { namespace is_simple
template <typename MultiPoint>
struct is_simple_multipoint
{
- static inline bool apply(MultiPoint const& multipoint)
+ template <typename Strategy>
+ static inline bool apply(MultiPoint const& multipoint, Strategy const&)
{
if (boost::empty(multipoint))
{
diff --git a/boost/geometry/algorithms/detail/is_valid/box.hpp b/boost/geometry/algorithms/detail/is_valid/box.hpp
index 863ce625fe..69a4d4e78e 100644
--- a/boost/geometry/algorithms/detail/is_valid/box.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/box.hpp
@@ -1,6 +1,6 @@
// 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
@@ -71,8 +71,8 @@ struct has_valid_corners<Box, 0>
template <typename Box>
struct is_valid_box
{
- template <typename VisitPolicy>
- static inline bool apply(Box const& box, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Box const& box, VisitPolicy& visitor, Strategy const&)
{
return
! has_invalid_coordinate<Box>::apply(box, visitor)
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 0a81213743..b91dc6a697 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
@@ -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
@@ -69,10 +70,11 @@ public:
> turn_type;
// returns true if all turns are valid
- template <typename Turns, typename VisitPolicy>
+ template <typename Turns, typename VisitPolicy, typename Strategy>
static inline bool apply(Geometry const& geometry,
Turns& turns,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
boost::ignore_unused(visitor);
@@ -85,6 +87,7 @@ public:
> interrupt_policy;
geometry::self_turns<turn_policy>(geometry,
+ strategy,
robust_policy,
turns,
interrupt_policy);
@@ -101,11 +104,11 @@ public:
}
// returns true if all turns are valid
- template <typename VisitPolicy>
- static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Geometry const& geometry, VisitPolicy& visitor, Strategy const& strategy)
{
std::vector<turn_type> turns;
- return apply(geometry, turns, visitor);
+ return apply(geometry, turns, visitor, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/interface.hpp b/boost/geometry/algorithms/detail/is_valid/interface.hpp
index 5a04a92824..ee013377c4 100644
--- a/boost/geometry/algorithms/detail/is_valid/interface.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/interface.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
@@ -23,48 +24,88 @@
#include <boost/geometry/policies/is_valid/default_policy.hpp>
#include <boost/geometry/policies/is_valid/failing_reason_policy.hpp>
#include <boost/geometry/policies/is_valid/failure_type_policy.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
namespace boost { namespace geometry
{
+
+namespace resolve_strategy
+{
+
+struct is_valid
+{
+ template <typename Geometry, typename VisitPolicy, typename Strategy>
+ static inline bool apply(Geometry const& geometry,
+ VisitPolicy& visitor,
+ Strategy const& strategy)
+ {
+ return dispatch::is_valid<Geometry>::apply(geometry, visitor, strategy);
+ }
+
+ template <typename Geometry, typename VisitPolicy>
+ static inline bool apply(Geometry const& geometry,
+ VisitPolicy& visitor,
+ default_strategy)
+ {
+ // NOTE: Currently the strategy is only used for Areal geometries
+ typedef typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >::type strategy_type;
+
+ return dispatch::is_valid<Geometry>::apply(geometry, visitor, strategy_type());
+ }
+};
+} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_variant
+{
template <typename Geometry>
struct is_valid
{
- template <typename VisitPolicy>
- static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Geometry const& geometry,
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
concepts::check<Geometry const>();
- return dispatch::is_valid<Geometry>::apply(geometry, visitor);
+
+ return resolve_strategy::is_valid::apply(geometry, visitor, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
struct visitor : boost::static_visitor<bool>
{
- visitor(VisitPolicy& policy) : m_policy(policy) {}
+ visitor(VisitPolicy& policy, Strategy const& strategy)
+ : m_policy(policy)
+ , m_strategy(strategy)
+ {}
template <typename Geometry>
bool operator()(Geometry const& geometry) const
{
- return is_valid<Geometry>::apply(geometry, m_policy);
+ return is_valid<Geometry>::apply(geometry, m_policy, m_strategy);
}
VisitPolicy& m_policy;
+ Strategy const& m_strategy;
};
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- VisitPolicy& policy_visitor)
+ VisitPolicy& policy_visitor,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<VisitPolicy>(policy_visitor),
+ return boost::apply_visitor(visitor<VisitPolicy, Strategy>(policy_visitor, strategy),
geometry);
}
};
@@ -73,10 +114,12 @@ struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
// Undocumented for now
-template <typename Geometry, typename VisitPolicy>
-inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor)
+template <typename Geometry, typename VisitPolicy, typename Strategy>
+inline bool is_valid(Geometry const& geometry,
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
- return resolve_variant::is_valid<Geometry>::apply(geometry, visitor);
+ return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
}
@@ -84,6 +127,29 @@ inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor)
\brief \brief_check{is valid (in the OGC sense)}
\ingroup is_valid
\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{Is_valid}
+\param geometry \param_geometry
+\param strategy \param_strategy{is_valid}
+\return \return_check{is valid (in the OGC sense);
+furthermore, the following geometries are considered valid:
+multi-geometries with no elements,
+linear geometries containing spikes,
+areal geometries with duplicate (consecutive) points}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/is_valid.qbk]}
+*/
+template <typename Geometry, typename Strategy>
+inline bool is_valid(Geometry const& geometry, Strategy const& strategy)
+{
+ is_valid_default_policy<> visitor;
+ return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
+}
+
+/*!
+\brief \brief_check{is valid (in the OGC sense)}
+\ingroup is_valid
+\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\return \return_check{is valid (in the OGC sense);
furthermore, the following geometries are considered valid:
@@ -96,8 +162,7 @@ inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor)
template <typename Geometry>
inline bool is_valid(Geometry const& geometry)
{
- is_valid_default_policy<> policy_visitor;
- return geometry::is_valid(geometry, policy_visitor);
+ return is_valid(geometry, default_strategy());
}
@@ -105,6 +170,33 @@ inline bool is_valid(Geometry const& geometry)
\brief \brief_check{is valid (in the OGC sense)}
\ingroup is_valid
\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{Is_valid}
+\param geometry \param_geometry
+\param failure An enumeration value indicating that the geometry is
+ valid or not, and if not valid indicating the reason why
+\param strategy \param_strategy{is_valid}
+\return \return_check{is valid (in the OGC sense);
+ furthermore, the following geometries are considered valid:
+ multi-geometries with no elements,
+ linear geometries containing spikes,
+ areal geometries with duplicate (consecutive) points}
+
+\qbk{distinguish,with failure value and strategy}
+\qbk{[include reference/algorithms/is_valid_with_failure.qbk]}
+*/
+template <typename Geometry, typename Strategy>
+inline bool is_valid(Geometry const& geometry, validity_failure_type& failure, Strategy const& strategy)
+{
+ failure_type_policy<> visitor;
+ bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
+ failure = visitor.failure();
+ return result;
+}
+
+/*!
+\brief \brief_check{is valid (in the OGC sense)}
+\ingroup is_valid
+\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\param failure An enumeration value indicating that the geometry is
valid or not, and if not valid indicating the reason why
@@ -120,10 +212,7 @@ inline bool is_valid(Geometry const& geometry)
template <typename Geometry>
inline bool is_valid(Geometry const& geometry, validity_failure_type& failure)
{
- failure_type_policy<> policy_visitor;
- bool result = geometry::is_valid(geometry, policy_visitor);
- failure = policy_visitor.failure();
- return result;
+ return is_valid(geometry, failure, default_strategy());
}
@@ -131,28 +220,52 @@ inline bool is_valid(Geometry const& geometry, validity_failure_type& failure)
\brief \brief_check{is valid (in the OGC sense)}
\ingroup is_valid
\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{Is_valid}
\param geometry \param_geometry
\param message A string containing a message stating if the geometry
is valid or not, and if not valid a reason why
+\param strategy \param_strategy{is_valid}
\return \return_check{is valid (in the OGC sense);
furthermore, the following geometries are considered valid:
multi-geometries with no elements,
linear geometries containing spikes,
areal geometries with duplicate (consecutive) points}
-\qbk{distinguish,with message}
+\qbk{distinguish,with message and strategy}
\qbk{[include reference/algorithms/is_valid_with_message.qbk]}
*/
-template <typename Geometry>
-inline bool is_valid(Geometry const& geometry, std::string& message)
+template <typename Geometry, typename Strategy>
+inline bool is_valid(Geometry const& geometry, std::string& message, Strategy const& strategy)
{
std::ostringstream stream;
- failing_reason_policy<> policy_visitor(stream);
- bool result = geometry::is_valid(geometry, policy_visitor);
+ failing_reason_policy<> visitor(stream);
+ bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
message = stream.str();
return result;
}
+/*!
+\brief \brief_check{is valid (in the OGC sense)}
+\ingroup is_valid
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\param message A string containing a message stating if the geometry
+ is valid or not, and if not valid a reason why
+\return \return_check{is valid (in the OGC sense);
+ furthermore, the following geometries are considered valid:
+ multi-geometries with no elements,
+ linear geometries containing spikes,
+ areal geometries with duplicate (consecutive) points}
+
+\qbk{distinguish,with message}
+\qbk{[include reference/algorithms/is_valid_with_message.qbk]}
+*/
+template <typename Geometry>
+inline bool is_valid(Geometry const& geometry, std::string& message)
+{
+ return is_valid(geometry, message, default_strategy());
+}
+
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/is_valid/linear.hpp b/boost/geometry/algorithms/detail/is_valid/linear.hpp
index a49e077237..6bc6b86cf8 100644
--- a/boost/geometry/algorithms/detail/is_valid/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/linear.hpp
@@ -1,6 +1,6 @@
// 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
@@ -77,6 +77,14 @@ struct is_valid_linestring
}
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);
+ }
};
@@ -142,9 +150,10 @@ private:
};
public:
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
static inline bool apply(MultiLinestring const& multilinestring,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const&)
{
if (BOOST_GEOMETRY_CONDITION(
AllowEmptyMultiGeometries && boost::empty(multilinestring)))
diff --git a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
index 0025445c2c..84dacc57f1 100644
--- a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
@@ -1,6 +1,6 @@
// 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
@@ -43,6 +43,8 @@
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+
namespace boost { namespace geometry
{
@@ -109,10 +111,10 @@ private:
geometry::partition
<
- geometry::model::box<typename point_type<MultiPolygon>::type>,
- typename base::expand_box,
- typename base::overlaps_box
- >::apply(polygon_iterators, item_visitor);
+ geometry::model::box<typename point_type<MultiPolygon>::type>
+ >::apply(polygon_iterators, item_visitor,
+ typename base::expand_box(),
+ typename base::overlaps_box());
if (item_visitor.items_overlap)
{
@@ -235,23 +237,28 @@ private:
}
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
struct per_polygon
{
- per_polygon(VisitPolicy& policy) : m_policy(policy) {}
+ per_polygon(VisitPolicy& policy, Strategy const& strategy)
+ : m_policy(policy)
+ , m_strategy(strategy)
+ {}
template <typename Polygon>
inline bool apply(Polygon const& polygon) const
{
- return base::apply(polygon, m_policy);
+ return base::apply(polygon, m_policy, m_strategy);
}
VisitPolicy& m_policy;
+ Strategy const& m_strategy;
};
public:
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
static inline bool apply(MultiPolygon const& multipolygon,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
typedef debug_validity_phase<MultiPolygon> debug_phase;
@@ -266,11 +273,11 @@ public:
if (! detail::check_iterator_range
<
- per_polygon<VisitPolicy>,
+ per_polygon<VisitPolicy, Strategy>,
false // do not check for empty multipolygon (done above)
>::apply(boost::begin(multipolygon),
boost::end(multipolygon),
- per_polygon<VisitPolicy>(visitor)))
+ per_polygon<VisitPolicy, Strategy>(visitor, strategy)))
{
return false;
}
@@ -283,7 +290,7 @@ public:
std::deque<typename has_valid_turns::turn_type> turns;
bool has_invalid_turns =
- ! has_valid_turns::apply(multipolygon, turns, visitor);
+ ! has_valid_turns::apply(multipolygon, turns, visitor, strategy);
debug_print_turns(turns.begin(), turns.end());
if (has_invalid_turns)
diff --git a/boost/geometry/algorithms/detail/is_valid/pointlike.hpp b/boost/geometry/algorithms/detail/is_valid/pointlike.hpp
index 51035f7a73..f77f7a35eb 100644
--- a/boost/geometry/algorithms/detail/is_valid/pointlike.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/pointlike.hpp
@@ -1,6 +1,6 @@
// 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
@@ -36,8 +36,8 @@ namespace dispatch
template <typename Point>
struct is_valid<Point, point_tag>
{
- template <typename VisitPolicy>
- static inline bool apply(Point const& point, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Point const& point, VisitPolicy& visitor, Strategy const&)
{
boost::ignore_unused(visitor);
return ! detail::is_valid::has_invalid_coordinate
@@ -56,9 +56,10 @@ struct is_valid<Point, point_tag>
template <typename MultiPoint, bool AllowEmptyMultiGeometries>
struct is_valid<MultiPoint, multi_point_tag, AllowEmptyMultiGeometries>
{
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
static inline bool apply(MultiPoint const& multipoint,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const&)
{
boost::ignore_unused(multipoint, visitor);
diff --git a/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
index bbe8e8fc39..f7e22fb8d2 100644
--- a/boost/geometry/algorithms/detail/is_valid/polygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/polygon.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
@@ -74,10 +75,13 @@ class is_valid_polygon
protected:
typedef debug_validity_phase<Polygon> debug_phase;
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
struct per_ring
{
- per_ring(VisitPolicy& policy) : m_policy(policy) {}
+ per_ring(VisitPolicy& policy, Strategy const& strategy)
+ : m_policy(policy)
+ , m_strategy(strategy)
+ {}
template <typename Ring>
inline bool apply(Ring const& ring) const
@@ -85,30 +89,34 @@ protected:
return detail::is_valid::is_valid_ring
<
Ring, false, true
- >::apply(ring, m_policy);
+ >::apply(ring, m_policy, m_strategy);
}
VisitPolicy& m_policy;
+ Strategy const& m_strategy;
};
- template <typename InteriorRings, typename VisitPolicy>
+ template <typename InteriorRings, typename VisitPolicy, typename Strategy>
static bool has_valid_interior_rings(InteriorRings const& interior_rings,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
return
detail::check_iterator_range
<
- per_ring<VisitPolicy>,
+ per_ring<VisitPolicy, Strategy>,
true // allow for empty interior ring range
>::apply(boost::begin(interior_rings),
boost::end(interior_rings),
- per_ring<VisitPolicy>(visitor));
+ per_ring<VisitPolicy, Strategy>(visitor, strategy));
}
struct has_valid_rings
{
- template <typename VisitPolicy>
- static inline bool apply(Polygon const& polygon, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Polygon const& polygon,
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
typedef typename ring_type<Polygon>::type ring_type;
@@ -119,7 +127,7 @@ protected:
<
ring_type,
false // do not check self intersections
- >::apply(exterior_ring(polygon), visitor))
+ >::apply(exterior_ring(polygon), visitor, strategy))
{
return false;
}
@@ -128,7 +136,8 @@ protected:
debug_phase::apply(2);
return has_valid_interior_rings(geometry::interior_rings(polygon),
- visitor);
+ visitor,
+ strategy);
}
};
@@ -246,10 +255,8 @@ protected:
geometry::partition
<
- geometry::model::box<typename point_type<Polygon>::type>,
- expand_box,
- overlaps_box
- >::apply(ring_iterators, item_visitor);
+ geometry::model::box<typename point_type<Polygon>::type>
+ >::apply(ring_iterators, item_visitor, expand_box(), overlaps_box());
if (item_visitor.items_overlap)
{
@@ -346,10 +353,12 @@ protected:
};
public:
- template <typename VisitPolicy>
- static inline bool apply(Polygon const& polygon, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Polygon const& polygon,
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
- if (! has_valid_rings::apply(polygon, visitor))
+ if (! has_valid_rings::apply(polygon, visitor, strategy))
{
return false;
}
@@ -366,7 +375,7 @@ public:
std::deque<typename has_valid_turns::turn_type> turns;
bool has_invalid_turns
- = ! has_valid_turns::apply(polygon, turns, visitor);
+ = ! has_valid_turns::apply(polygon, turns, visitor, strategy);
debug_print_turns(turns.begin(), turns.end());
if (has_invalid_turns)
diff --git a/boost/geometry/algorithms/detail/is_valid/ring.hpp b/boost/geometry/algorithms/detail/is_valid/ring.hpp
index 925c03a472..9ab68fdc48 100644
--- a/boost/geometry/algorithms/detail/is_valid/ring.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/ring.hpp
@@ -1,6 +1,6 @@
// 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
@@ -101,26 +101,21 @@ struct ring_area_predicate<ResultType, true>
template <typename Ring, bool IsInteriorRing>
struct is_properly_oriented
{
- typedef typename point_type<Ring>::type point_type;
-
- typedef typename strategy::area::services::default_strategy
- <
- typename cs_tag<point_type>::type,
- point_type
- >::type strategy_type;
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Ring const& ring, VisitPolicy& visitor,
+ Strategy const& strategy)
+ {
+ boost::ignore_unused(visitor);
- typedef detail::area::ring_area
- <
- order_as_direction<geometry::point_order<Ring>::value>::value,
- geometry::closure<Ring>::value
- > ring_area_type;
+ typedef typename point_type<Ring>::type point_type;
- typedef typename default_area_result<Ring>::type area_result_type;
+ typedef detail::area::ring_area
+ <
+ order_as_direction<geometry::point_order<Ring>::value>::value,
+ geometry::closure<Ring>::value
+ > ring_area_type;
- template <typename VisitPolicy>
- static inline bool apply(Ring const& ring, VisitPolicy& visitor)
- {
- boost::ignore_unused(visitor);
+ typedef typename default_area_result<Ring>::type area_result_type;
typename ring_area_predicate
<
@@ -128,8 +123,11 @@ struct is_properly_oriented
>::type predicate;
// Check area
- area_result_type const zero = area_result_type();
- if (predicate(ring_area_type::apply(ring, strategy_type()), zero))
+ area_result_type const zero = 0;
+ area_result_type const area
+ = ring_area_type::apply(ring,
+ strategy.template get_area_strategy<point_type>());
+ if (predicate(area, zero))
{
return visitor.template apply<no_failure>();
}
@@ -150,8 +148,9 @@ template
>
struct is_valid_ring
{
- template <typename VisitPolicy>
- static inline bool apply(Ring const& ring, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Ring const& ring, VisitPolicy& visitor,
+ Strategy const& strategy)
{
// return invalid if any of the following condition holds:
// (a) the ring's point coordinates are not invalid (e.g., NaN)
@@ -198,8 +197,8 @@ struct is_valid_ring
&& ! has_duplicates<Ring, closure>::apply(ring, visitor)
&& ! has_spikes<Ring, closure>::apply(ring, visitor)
&& (! CheckSelfIntersections
- || has_valid_self_turns<Ring>::apply(ring, visitor))
- && is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor);
+ || 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/is_valid/segment.hpp b/boost/geometry/algorithms/detail/is_valid/segment.hpp
index f92f73381f..30cbf7afdb 100644
--- a/boost/geometry/algorithms/detail/is_valid/segment.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/segment.hpp
@@ -1,6 +1,6 @@
// 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
@@ -44,8 +44,8 @@ namespace dispatch
template <typename Segment>
struct is_valid<Segment, segment_tag>
{
- template <typename VisitPolicy>
- static inline bool apply(Segment const& segment, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Segment const& segment, VisitPolicy& visitor, Strategy const&)
{
boost::ignore_unused(visitor);
diff --git a/boost/geometry/algorithms/detail/not.hpp b/boost/geometry/algorithms/detail/not.hpp
index 43e71e2e37..95cdfa24e6 100644
--- a/boost/geometry/algorithms/detail/not.hpp
+++ b/boost/geometry/algorithms/detail/not.hpp
@@ -4,10 +4,11 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -46,6 +47,14 @@ struct not_
{
return ! Policy::apply(geometry1, geometry2);
}
+
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return ! Policy::apply(geometry1, geometry2, strategy);
+ }
};
diff --git a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
index 047eb4993e..2408b4b68e 100644
--- a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
+++ b/boost/geometry/algorithms/detail/overlay/assign_parents.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)
@@ -258,8 +262,9 @@ inline void assign_parents(Geometry1 const& geometry1,
geometry::partition
<
- box_type, ring_info_helper_get_box, ring_info_helper_ovelaps_box
- >::apply(vector, visitor);
+ box_type
+ >::apply(vector, visitor, ring_info_helper_get_box(),
+ ring_info_helper_ovelaps_box());
}
if (check_for_orientation)
diff --git a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
index a8171e1482..9beb8ad64f 100644
--- a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
+++ b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.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)
@@ -106,19 +110,27 @@ class backtrack_check_self_intersections
public :
typedef state state_type;
- template <typename Operation, typename Rings, typename Ring, typename Turns, typename RobustPolicy, typename Visitor>
+ template
+ <
+ typename Operation,
+ typename Rings, typename Ring, typename Turns,
+ typename Strategy,
+ typename RobustPolicy,
+ typename Visitor
+ >
static inline void apply(std::size_t size_at_start,
- Rings& rings, Ring& ring,
- Turns& turns,
- typename boost::range_value<Turns>::type const& turn,
- Operation& operation,
- traverse_error_type traverse_error,
- Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- RobustPolicy const& robust_policy,
- state_type& state,
- Visitor& visitor
- )
+ Rings& rings,
+ Ring& ring,
+ Turns& turns,
+ typename boost::range_value<Turns>::type const& turn,
+ Operation& operation,
+ traverse_error_type traverse_error,
+ Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy,
+ RobustPolicy const& robust_policy,
+ state_type& state,
+ Visitor& visitor)
{
visitor.visit_traverse_reject(turns, turn, operation, traverse_error);
@@ -128,8 +140,8 @@ public :
if (! state.m_checked)
{
state.m_checked = true;
- has_self_intersections(geometry1, robust_policy);
- has_self_intersections(geometry2, robust_policy);
+ has_self_intersections(geometry1, strategy, robust_policy);
+ has_self_intersections(geometry2, strategy, robust_policy);
}
// Make bad output clean
diff --git a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
index b9e48cdbfc..c249ff57ff 100644
--- a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
@@ -1,5 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
// Licensed under the Boost Software License version 1.0.
@@ -15,6 +17,7 @@
#include <iterator>
#include <boost/range.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/tag.hpp>
@@ -307,7 +310,7 @@ public:
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
if (enter_count != 0)
{
- throw inconsistent_turns_exception();
+ BOOST_THROW_EXCEPTION(inconsistent_turns_exception());
}
#else
BOOST_GEOMETRY_ASSERT(enter_count == 0);
diff --git a/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp
index 99281eaecb..94667d0ed0 100644
--- a/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_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)
@@ -39,29 +44,33 @@ template
>
struct get_turn_without_info
{
- template <typename RobustPolicy, typename OutputIterator>
+ template <typename Strategy, typename RobustPolicy, typename OutputIterator>
static inline OutputIterator apply(
Point1 const& pi, Point1 const& pj, Point1 const& /*pk*/,
Point2 const& qi, Point2 const& qj, Point2 const& /*qk*/,
bool /*is_p_first*/, bool /*is_p_last*/,
bool /*is_q_first*/, bool /*is_q_last*/,
TurnInfo const& ,
+ Strategy const& strategy,
RobustPolicy const& robust_policy,
OutputIterator out)
{
- typedef intersection_strategies
- <
- typename cs_tag<typename TurnInfo::point_type>::type,
- Point1,
- Point2,
- typename TurnInfo::point_type,
- RobustPolicy
- > si;
+ typedef typename TurnInfo::point_type turn_point_type;
- typedef typename si::segment_intersection_strategy_type strategy;
+ typedef policies::relate::segments_intersection_points
+ <
+ segment_intersection_points
+ <
+ turn_point_type,
+ typename geometry::segment_ratio_type
+ <
+ turn_point_type, RobustPolicy
+ >::type
+ >
+ > policy_type;
typedef model::referring_segment<Point1 const> segment_type1;
- typedef model::referring_segment<Point1 const> segment_type2;
+ typedef model::referring_segment<Point2 const> segment_type2;
segment_type1 p1(pi, pj);
segment_type2 q1(qi, qj);
@@ -75,15 +84,14 @@ struct get_turn_without_info
geometry::recalculate(pj_rob, pj, robust_policy);
geometry::recalculate(qi_rob, qi, robust_policy);
geometry::recalculate(qj_rob, qj, robust_policy);
- typename strategy::return_type result
- = strategy::apply(p1, q1, robust_policy,
- pi_rob, pj_rob, qi_rob, qj_rob);
+ typename policy_type::return_type result
+ = strategy.apply(p1, q1, policy_type(), robust_policy,
+ pi_rob, pj_rob, qi_rob, qj_rob);
- for (std::size_t i = 0; i < result.template get<0>().count; i++)
+ for (std::size_t i = 0; i < result.count; i++)
{
-
TurnInfo tp;
- geometry::convert(result.template get<0>().intersections[i], tp.point);
+ geometry::convert(result.intersections[i], tp.point);
*out++ = tp;
}
@@ -102,12 +110,14 @@ template
typename Geometry1,
typename Geometry2,
typename RobustPolicy,
- typename Turns
+ typename Turns,
+ typename Strategy
>
inline void get_intersection_points(Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
- Turns& turns)
+ Turns& turns,
+ Strategy const& strategy)
{
concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2 const>();
@@ -142,6 +152,7 @@ inline void get_intersection_points(Geometry1 const& geometry1,
>::type::apply(
0, geometry1,
1, geometry2,
+ strategy,
robust_policy,
turns, interrupt_policy);
}
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
index a4cce3fd32..08bc342186 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
@@ -1,9 +1,10 @@
// 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 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
@@ -16,10 +17,10 @@
#include <boost/core/ignore_unused.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
-#include <boost/geometry/strategies/intersection_strategies.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
@@ -644,7 +645,7 @@ struct collinear : public base_turn_handler
// 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>(b) - get<1>(b);
+ ctype const dy = get<1>(a) - get<1>(b);
return dx * dx + dy * dy;
}
};
@@ -930,6 +931,7 @@ struct get_turn_info
typename Point1,
typename Point2,
typename TurnInfo,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename OutputIterator
>
@@ -939,13 +941,19 @@ struct get_turn_info
bool /*is_p_first*/, bool /*is_p_last*/,
bool /*is_q_first*/, bool /*is_q_last*/,
TurnInfo const& tp_model,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
OutputIterator out)
{
- typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
- inters_info;
+ typedef intersection_info
+ <
+ Point1, Point2,
+ typename TurnInfo::point_type,
+ IntersectionStrategy,
+ RobustPolicy
+ > inters_info;
- inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy);
+ inters_info inters(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy);
char const method = inters.d_info().how;
@@ -991,9 +999,12 @@ struct get_turn_info
<
typename inters_info::cs_tag,
typename inters_info::robust_point2_type,
- typename inters_info::robust_point1_type
+ typename inters_info::robust_point1_type,
+ typename inters_info::side_strategy_type
> swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),
- inters.rpi(), inters.rpj(), inters.rpk());
+ inters.rpi(), inters.rpj(), inters.rpk(),
+ inters.get_side_strategy());
+
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
tp, inters.i_info(), inters.d_info(),
swapped_side_calc);
@@ -1093,7 +1104,7 @@ struct get_turn_info
std::cout << "TURN: Unknown method: " << method << std::endl;
#endif
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
- throw turn_info_exception(method);
+ BOOST_THROW_EXCEPTION(turn_info_exception(method));
#endif
}
break;
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
index 85cdfbc02d..48716634c5 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
@@ -2,15 +2,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// 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, 2014, 2017.
+// Modifications copyright (c) 2013-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_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP
@@ -427,8 +427,11 @@ struct get_turn_info_for_endpoint
}
else if ( ip_j2 )
{
- side_calculator<cs_tag, RobustPoint1, RobustPoint2, RobustPoint2>
- side_calc(ri2, ri1, rj1, ri2, rj2, rk2);
+ side_calculator<cs_tag,
+ RobustPoint1, RobustPoint2,
+ typename IntersectionInfo::side_strategy_type,
+ RobustPoint2>
+ side_calc(ri2, ri1, rj1, ri2, rj2, rk2, inters.get_side_strategy());
std::pair<operation_type, operation_type>
operations = operations_of_equal(side_calc);
@@ -478,8 +481,10 @@ struct get_turn_info_for_endpoint
}
else if ( ip_j2 )
{
- side_calculator<cs_tag, RobustPoint1, RobustPoint2, RobustPoint2>
- side_calc(ri2, rj1, ri1, ri2, rj2, rk2);
+ side_calculator<cs_tag, RobustPoint1, RobustPoint2,
+ typename IntersectionInfo::side_strategy_type,
+ RobustPoint2>
+ side_calc(ri2, rj1, ri1, ri2, rj2, rk2, inters.get_side_strategy());
std::pair<operation_type, operation_type>
operations = operations_of_equal(side_calc);
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 3e7da1d797..5f2cb07faf 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
@@ -2,15 +2,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// 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
// Use, modification and distribution is subject to the 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_OVERLAY_GET_TURN_INFO_HELPERS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP
@@ -37,32 +37,27 @@ struct turn_operation_linear
};
template <typename TurnPointCSTag, typename PointP, typename PointQ,
+ typename SideStrategy,
typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,
typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ
>
struct side_calculator
{
- // This strategy should be the same as side strategy defined in
- // intersection_strategies<> which is used in various places
- // of the library
- typedef typename strategy::side::services::default_strategy
- <
- TurnPointCSTag
- >::type side;
-
inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk,
- Qi const& qi, Qj const& qj, Qk const& qk)
+ Qi const& qi, Qj const& qj, Qk const& qk,
+ SideStrategy const& side_strategy)
: m_pi(pi), m_pj(pj), m_pk(pk)
, m_qi(qi), m_qj(qj), m_qk(qk)
+ , m_side_strategy(side_strategy)
{}
- inline int pk_wrt_p1() const { return side::apply(m_pi, m_pj, m_pk); }
- inline int pk_wrt_q1() const { return side::apply(m_qi, m_qj, m_pk); }
- inline int qk_wrt_p1() const { return side::apply(m_pi, m_pj, m_qk); }
- inline int qk_wrt_q1() const { return side::apply(m_qi, m_qj, m_qk); }
+ inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); }
+ inline int pk_wrt_q1() const { return m_side_strategy.apply(m_qi, m_qj, m_pk); }
+ inline int qk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_qk); }
+ inline int qk_wrt_q1() const { return m_side_strategy.apply(m_qi, m_qj, m_qk); }
- inline int pk_wrt_q2() const { return side::apply(m_qj, m_qk, m_pk); }
- inline int qk_wrt_p2() const { return side::apply(m_pj, m_pk, m_qk); }
+ inline int pk_wrt_q2() const { return m_side_strategy.apply(m_qj, m_qk, m_pk); }
+ inline int qk_wrt_p2() const { return m_side_strategy.apply(m_pj, m_pk, m_qk); }
Pi const& m_pi;
Pj const& m_pj;
@@ -70,6 +65,8 @@ struct side_calculator
Qi const& m_qi;
Qj const& m_qj;
Qk const& m_qk;
+
+ SideStrategy const& m_side_strategy;
};
template <typename Point1, typename Point2, typename RobustPolicy>
@@ -99,7 +96,7 @@ struct robust_points
robust_point2_type m_rqi, m_rqj, m_rqk;
};
-template <typename Point1, typename Point2, typename TurnPoint, typename RobustPolicy>
+template <typename Point1, typename Point2, typename TurnPoint, typename IntersectionStrategy, typename RobustPolicy>
class intersection_info_base
: private robust_points<Point1, Point2, RobustPolicy>
{
@@ -114,14 +111,17 @@ public:
typedef typename cs_tag<TurnPoint>::type cs_tag;
- typedef side_calculator<cs_tag, robust_point1_type, robust_point2_type> side_calculator_type;
+ typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
+ typedef side_calculator<cs_tag, robust_point1_type, robust_point2_type, side_strategy_type> side_calculator_type;
intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy)
: base(pi, pj, pk, qi, qj, qk, robust_policy)
, m_side_calc(base::m_rpi, base::m_rpj, base::m_rpk,
- base::m_rqi, base::m_rqj, base::m_rqk)
+ base::m_rqi, base::m_rqj, base::m_rqk,
+ intersection_strategy.get_side_strategy())
, m_pi(pi), m_pj(pj), m_pk(pk)
, m_qi(qi), m_qj(qj), m_qk(qk)
{}
@@ -155,8 +155,8 @@ private:
point2_type const& m_qk;
};
-template <typename Point1, typename Point2, typename TurnPoint>
-class intersection_info_base<Point1, Point2, TurnPoint, detail::no_rescale_policy>
+template <typename Point1, typename Point2, typename TurnPoint, typename IntersectionStrategy>
+class intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, detail::no_rescale_policy>
{
public:
typedef Point1 point1_type;
@@ -167,12 +167,15 @@ public:
typedef typename cs_tag<TurnPoint>::type cs_tag;
- typedef side_calculator<cs_tag, Point1, Point2> side_calculator_type;
+ typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
+ typedef side_calculator<cs_tag, Point1, Point2, side_strategy_type> side_calculator_type;
intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ IntersectionStrategy const& intersection_strategy,
no_rescale_policy const& /*robust_policy*/)
- : m_side_calc(pi, pj, pk, qi, qj, qk)
+ : m_side_calc(pi, pj, pk, qi, qj, qk,
+ intersection_strategy.get_side_strategy())
{}
inline Point1 const& pi() const { return m_side_calc.m_pi; }
@@ -203,40 +206,58 @@ template
typename Point1,
typename Point2,
typename TurnPoint,
+ typename IntersectionStrategy,
typename RobustPolicy
>
class intersection_info
- : public intersection_info_base<Point1, Point2, TurnPoint, RobustPolicy>
+ : public intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, RobustPolicy>
{
- typedef intersection_info_base<Point1, Point2, TurnPoint, RobustPolicy> base;
+ typedef intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, RobustPolicy> base;
+
+public:
+ typedef segment_intersection_points
+ <
+ TurnPoint,
+ typename geometry::segment_ratio_type
+ <
+ TurnPoint, RobustPolicy
+ >::type
+ > intersection_point_type;
- typedef typename intersection_strategies
+ // NOTE: formerly defined in intersection_strategies
+ typedef policies::relate::segments_tupled
<
- typename base::cs_tag,
- Point1,
- Point2,
- TurnPoint,
- RobustPolicy
- >::segment_intersection_strategy_type strategy;
+ policies::relate::segments_intersection_points
+ <
+ intersection_point_type
+ >,
+ policies::relate::segments_direction
+ > intersection_policy_type;
+
+ typedef IntersectionStrategy intersection_strategy_type;
+ typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
-public:
typedef model::referring_segment<Point1 const> segment_type1;
typedef model::referring_segment<Point2 const> segment_type2;
typedef typename base::side_calculator_type side_calculator_type;
- typedef typename strategy::return_type result_type;
+ typedef typename intersection_policy_type::return_type result_type;
typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info
typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info
intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy)
- : base(pi, pj, pk, qi, qj, qk, robust_policy)
- , m_result(strategy::apply(segment_type1(pi, pj),
- segment_type2(qi, qj),
- robust_policy,
- base::rpi(), base::rpj(),
- base::rqi(), base::rqj()))
+ : base(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy)
+ , m_result(intersection_strategy.apply(
+ segment_type1(pi, pj),
+ segment_type2(qi, qj),
+ intersection_policy_type(),
+ robust_policy,
+ base::rpi(), base::rpj(),
+ base::rqi(), base::rqj()))
+ , m_intersection_strategy(intersection_strategy)
, m_robust_policy(robust_policy)
{}
@@ -244,6 +265,16 @@ public:
inline i_info_type const& i_info() const { return m_result.template get<0>(); }
inline d_info_type const& d_info() const { return m_result.template get<1>(); }
+ inline intersection_strategy_type const& get_intersection_strategy() const
+ {
+ return m_intersection_strategy;
+ }
+
+ inline side_strategy_type get_side_strategy() const
+ {
+ return m_intersection_strategy.get_side_strategy();
+ }
+
// TODO: it's more like is_spike_ip_p
inline bool is_spike_p() const
{
@@ -307,17 +338,18 @@ private:
{
typedef model::referring_segment<Point const> seg;
- typedef intersection_strategies
- <
- typename base::cs_tag, Point, Point, Point, RobustPolicy
- > si;
-
- typedef typename si::segment_intersection_strategy_type strategy;
-
- typename strategy::return_type result
- = strategy::apply(seg(i, j), seg(j, k), m_robust_policy);
+ // no need to calcualte direction info
+ typedef policies::relate::segments_intersection_points
+ <
+ intersection_point_type
+ > policy_type;
+
+ typename policy_type::return_type const result
+ = m_intersection_strategy.apply(seg(i, j), seg(j, k),
+ policy_type(),
+ m_robust_policy);
- return result.template get<0>().count == 2;
+ return result.count == 2;
}
template <std::size_t OpId>
@@ -344,6 +376,7 @@ private:
}
result_type m_result;
+ IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_robust_policy;
};
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
index 121728d822..46c1305cd7 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
@@ -1,9 +1,10 @@
// 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 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
@@ -14,6 +15,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP
+#include <boost/throw_exception.hpp>
+
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/condition.hpp>
@@ -41,6 +44,7 @@ struct get_turn_info_linear_areal
typename Point1,
typename Point2,
typename TurnInfo,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename OutputIterator
>
@@ -50,13 +54,19 @@ struct get_turn_info_linear_areal
bool is_p_first, bool is_p_last,
bool is_q_first, bool is_q_last,
TurnInfo const& tp_model,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
OutputIterator out)
{
- typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
- inters_info;
+ typedef intersection_info
+ <
+ Point1, Point2,
+ typename TurnInfo::point_type,
+ IntersectionStrategy,
+ RobustPolicy
+ > inters_info;
- inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy);
+ inters_info inters(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy);
char const method = inters.d_info().how;
@@ -108,9 +118,11 @@ struct get_turn_info_linear_areal
<
typename inters_info::cs_tag,
typename inters_info::robust_point2_type,
- typename inters_info::robust_point1_type
+ typename inters_info::robust_point1_type,
+ typename inters_info::side_strategy_type
> swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),
- inters.rpi(), inters.rpj(), inters.rpk());
+ inters.rpi(), inters.rpj(), inters.rpk(),
+ inters.get_side_strategy());
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
tp, inters.i_info(), inters.d_info(),
swapped_side_calc);
@@ -395,7 +407,7 @@ struct get_turn_info_linear_areal
std::cout << "TURN: Unknown method: " << method << std::endl;
#endif
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
- throw turn_info_exception(method);
+ BOOST_THROW_EXCEPTION(turn_info_exception(method));
#endif
}
break;
@@ -747,6 +759,9 @@ struct get_turn_info_linear_areal
}
else
{
+ typedef typename IntersectionInfo::robust_point1_type rp1_type;
+ typedef typename IntersectionInfo::robust_point2_type rp2_type;
+
method_type replaced_method = method_touch_interior;
if ( ip0.is_qj )
@@ -754,11 +769,12 @@ struct get_turn_info_linear_areal
side_calculator
<
typename IntersectionInfo::cs_tag,
- typename IntersectionInfo::robust_point1_type,
- typename IntersectionInfo::robust_point2_type,
- typename IntersectionInfo::robust_point2_type
+ rp1_type, rp2_type,
+ typename IntersectionInfo::side_strategy_type,
+ rp2_type
> side_calc(inters.rqi(), inters.rpi(), inters.rpj(),
- inters.rqi(), inters.rqj(), inters.rqk());
+ inters.rqi(), inters.rqj(), inters.rqk(),
+ inters.get_side_strategy());
std::pair<operation_type, operation_type>
operations = get_info_e::operations_of_equal(side_calc);
@@ -773,16 +789,13 @@ struct get_turn_info_linear_areal
side_calculator
<
typename IntersectionInfo::cs_tag,
- typename IntersectionInfo::robust_point1_type,
- typename IntersectionInfo::robust_point2_type,
- typename IntersectionInfo::robust_point2_type,
- typename IntersectionInfo::robust_point1_type,
- typename IntersectionInfo::robust_point1_type,
- typename IntersectionInfo::robust_point2_type,
- typename IntersectionInfo::robust_point1_type,
- typename IntersectionInfo::robust_point2_type
+ rp1_type, rp2_type,
+ typename IntersectionInfo::side_strategy_type,
+ rp2_type, rp1_type, rp1_type,
+ rp2_type, rp1_type, rp2_type
> side_calc(inters.rqi(), inters.rpi(), inters.rpj(),
- inters.rqi(), inters.rpi(), inters.rqj());
+ inters.rqi(), inters.rpi(), inters.rqj(),
+ inters.get_side_strategy());
std::pair<operation_type, operation_type>
operations = get_info_e::operations_of_equal(side_calc);
@@ -832,9 +845,11 @@ struct get_turn_info_linear_areal
typename IntersectionInfo::cs_tag,
typename IntersectionInfo::robust_point1_type,
typename IntersectionInfo::robust_point2_type,
+ typename IntersectionInfo::side_strategy_type,
typename IntersectionInfo::robust_point2_type
> side_calc(inters.rqi(), inters.rpj(), inters.rpi(),
- inters.rqi(), inters.rqj(), inters.rqk());
+ inters.rqi(), inters.rqj(), inters.rqk(),
+ inters.get_side_strategy());
std::pair<operation_type, operation_type>
operations = get_info_e::operations_of_equal(side_calc);
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
index 6bb3a74bb8..58fd4bb5c7 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
@@ -1,19 +1,22 @@
// 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 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
// Use, modification and distribution is subject to the 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_OVERLAY_GET_TURN_INFO_LL_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP
+#include <boost/throw_exception.hpp>
+
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
@@ -36,6 +39,7 @@ struct get_turn_info_linear_linear
typename Point1,
typename Point2,
typename TurnInfo,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename OutputIterator
>
@@ -45,13 +49,19 @@ struct get_turn_info_linear_linear
bool is_p_first, bool is_p_last,
bool is_q_first, bool is_q_last,
TurnInfo const& tp_model,
+ IntersectionStrategy const& strategy,
RobustPolicy const& robust_policy,
OutputIterator out)
{
- typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
- inters_info;
+ typedef intersection_info
+ <
+ Point1, Point2,
+ typename TurnInfo::point_type,
+ IntersectionStrategy,
+ RobustPolicy
+ > inters_info;
- inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy);
+ inters_info inters(pi, pj, pk, qi, qj, qk, strategy, robust_policy);
char const method = inters.d_info().how;
@@ -103,9 +113,11 @@ struct get_turn_info_linear_linear
<
typename inters_info::cs_tag,
typename inters_info::robust_point2_type,
- typename inters_info::robust_point1_type
+ typename inters_info::robust_point1_type,
+ typename inters_info::side_strategy_type
> swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),
- inters.rpi(), inters.rpj(), inters.rpk());
+ inters.rpi(), inters.rpj(), inters.rpk(),
+ inters.get_side_strategy());
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
tp, inters.i_info(), inters.d_info(),
@@ -463,7 +475,7 @@ struct get_turn_info_linear_linear
std::cout << "TURN: Unknown method: " << method << std::endl;
#endif
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
- throw turn_info_exception(method);
+ BOOST_THROW_EXCEPTION(turn_info_exception(method));
#endif
}
break;
diff --git a/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
index 1eb18b74d4..4e97a84a37 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turns.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
@@ -3,15 +3,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014, 2016.
-// Modifications copyright (c) 2014, 2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016, 2017.
+// Modifications 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_OVERLAY_GET_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP
@@ -45,7 +45,6 @@
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
-#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
#include <boost/geometry/strategies/intersection_strategies.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
@@ -174,11 +173,12 @@ class get_turns_in_sections
public :
// Returns true if terminated, false if interrupted
- template <typename Turns, typename RobustPolicy, typename InterruptPolicy>
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline bool apply(
int source_id1, Geometry1 const& geometry1, Section1 const& sec1,
int source_id2, Geometry2 const& geometry2, Section2 const& sec2,
bool skip_larger,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy)
@@ -295,7 +295,8 @@ public :
TurnPolicy::apply(*prev1, *it1, *nd_next1, *prev2, *it2, *nd_next2,
is_1_first, is_1_last, is_2_first, is_2_last,
- ti, robust_policy, std::back_inserter(turns));
+ ti, intersection_strategy, robust_policy,
+ std::back_inserter(turns));
if (InterruptPolicy::enabled)
{
@@ -381,9 +382,10 @@ template
<
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2,
- typename Turns,
typename TurnPolicy,
+ typename IntersectionStrategy,
typename RobustPolicy,
+ typename Turns,
typename InterruptPolicy
>
struct section_visitor
@@ -392,16 +394,20 @@ struct section_visitor
Geometry1 const& m_geometry1;
int m_source_id2;
Geometry2 const& m_geometry2;
+ IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_rescale_policy;
Turns& m_turns;
InterruptPolicy& m_interrupt_policy;
section_visitor(int id1, Geometry1 const& g1,
- int id2, Geometry2 const& g2,
- RobustPolicy const& robust_policy,
- Turns& turns, InterruptPolicy& ip)
+ int id2, Geometry2 const& g2,
+ IntersectionStrategy const& intersection_strategy,
+ RobustPolicy const& robust_policy,
+ Turns& turns,
+ InterruptPolicy& ip)
: m_source_id1(id1), m_geometry1(g1)
, m_source_id2(id2), m_geometry2(g2)
+ , m_intersection_strategy(intersection_strategy)
, m_rescale_policy(robust_policy)
, m_turns(turns)
, m_interrupt_policy(ip)
@@ -423,6 +429,7 @@ struct section_visitor
m_source_id1, m_geometry1, sec1,
m_source_id2, m_geometry2, sec2,
false,
+ m_intersection_strategy,
m_rescale_policy,
m_turns, m_interrupt_policy);
}
@@ -441,10 +448,11 @@ class get_turns_generic
{
public:
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline void apply(
int source_id1, Geometry1 const& geometry1,
int source_id2, Geometry2 const& geometry2,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy)
@@ -475,15 +483,19 @@ public:
<
Geometry1, Geometry2,
Reverse1, Reverse2,
- Turns, TurnPolicy, RobustPolicy, InterruptPolicy
- > visitor(source_id1, geometry1, source_id2, geometry2, robust_policy, turns, interrupt_policy);
+ TurnPolicy,
+ IntersectionStrategy, RobustPolicy,
+ Turns, InterruptPolicy
+ > visitor(source_id1, geometry1, source_id2, geometry2,
+ intersection_strategy, robust_policy,
+ turns, interrupt_policy);
geometry::partition
<
- box_type,
- detail::section::get_section_box,
- detail::section::overlaps_section_box
- >::apply(sec1, sec2, visitor);
+ box_type
+ >::apply(sec1, sec2, visitor,
+ detail::section::get_section_box(),
+ detail::section::overlaps_section_box());
}
};
@@ -518,10 +530,11 @@ struct get_turns_cs
>::type iterator_type;
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline void apply(
int source_id1, Range const& range,
int source_id2, Box const& box,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy,
@@ -593,8 +606,10 @@ struct get_turns_cs
// NOTE: some dummy values could be passed below since this would be called only for Polygons and Boxes
index == 0,
size_type(index) == segments_count1,
+ intersection_strategy,
robust_policy,
- turns, interrupt_policy);
+ turns,
+ interrupt_policy);
// Future performance enhancement:
// return if told by the interrupt policy
}
@@ -622,7 +637,7 @@ private:
else return 0;
}
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline void get_turns_with_box(segment_identifier const& seg_id, int source_id2,
// Points from a range:
point_type const& rp0,
@@ -635,6 +650,7 @@ private:
box_point_type const& bp3,
bool const is_range_first,
bool const is_range_last,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
// Output
Turns& turns,
@@ -653,25 +669,29 @@ private:
TurnPolicy::apply(rp0, rp1, rp2, bp0, bp1, bp2,
is_range_first, is_range_last,
true, false,
- ti, robust_policy, std::back_inserter(turns));
+ ti, intersection_strategy, robust_policy,
+ std::back_inserter(turns));
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 1);
TurnPolicy::apply(rp0, rp1, rp2, bp1, bp2, bp3,
is_range_first, is_range_last,
false, false,
- ti, robust_policy, std::back_inserter(turns));
+ ti, intersection_strategy, robust_policy,
+ std::back_inserter(turns));
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 2);
TurnPolicy::apply(rp0, rp1, rp2, bp2, bp3, bp0,
is_range_first, is_range_last,
false, false,
- ti, robust_policy, std::back_inserter(turns));
+ ti, intersection_strategy, robust_policy,
+ std::back_inserter(turns));
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3);
TurnPolicy::apply(rp0, rp1, rp2, bp3, bp0, bp1,
is_range_first, is_range_last,
false, true,
- ti, robust_policy, std::back_inserter(turns));
+ ti, intersection_strategy, robust_policy,
+ std::back_inserter(turns));
if (InterruptPolicy::enabled)
{
@@ -691,12 +711,14 @@ template
>
struct get_turns_polygon_cs
{
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline void apply(
int source_id1, Polygon const& polygon,
int source_id2, Box const& box,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
- Turns& turns, InterruptPolicy& interrupt_policy,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy,
signed_size_type multi_index = -1)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
@@ -711,8 +733,10 @@ struct get_turns_polygon_cs
intersector_type::apply(
source_id1, geometry::exterior_ring(polygon),
source_id2, box,
+ intersection_strategy,
robust_policy,
- turns, interrupt_policy,
+ turns,
+ interrupt_policy,
multi_index, -1);
signed_size_type i = 0;
@@ -725,6 +749,7 @@ struct get_turns_polygon_cs
intersector_type::apply(
source_id1, *it,
source_id2, box,
+ intersection_strategy,
robust_policy,
turns, interrupt_policy,
multi_index, i);
@@ -742,12 +767,14 @@ template
>
struct get_turns_multi_polygon_cs
{
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline void apply(
int source_id1, Multi const& multi,
int source_id2, Box const& box,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
- Turns& turns, InterruptPolicy& interrupt_policy)
+ Turns& turns,
+ InterruptPolicy& interrupt_policy)
{
typedef typename boost::range_iterator
<
@@ -766,7 +793,8 @@ struct get_turns_multi_polygon_cs
Reverse, ReverseBox,
TurnPolicy
>::apply(source_id1, *it, source_id2, box,
- robust_policy, turns, interrupt_policy, i);
+ intersection_strategy, robust_policy,
+ turns, interrupt_policy, i);
}
}
};
@@ -918,13 +946,13 @@ template
>
struct get_turns_reversed
{
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
- static inline void apply(
- int source_id1, Geometry1 const& g1,
- int source_id2, Geometry2 const& g2,
- RobustPolicy const& robust_policy,
- Turns& turns,
- InterruptPolicy& interrupt_policy)
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ static inline void apply(int source_id1, Geometry1 const& g1,
+ int source_id2, Geometry2 const& g2,
+ IntersectionStrategy const& intersection_strategy,
+ RobustPolicy const& robust_policy,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy)
{
get_turns
<
@@ -932,8 +960,9 @@ struct get_turns_reversed
Geometry2, Geometry1,
Reverse2, Reverse1,
TurnPolicy
- >::apply(source_id2, g2, source_id1, g1, robust_policy,
- turns, interrupt_policy);
+ >::apply(source_id2, g2, source_id1, g1,
+ intersection_strategy, robust_policy,
+ turns, interrupt_policy);
}
};
@@ -951,6 +980,7 @@ struct get_turns_reversed
\tparam Turns type of turn-container (e.g. vector of "intersection/turn point"'s)
\param geometry1 \param_geometry
\param geometry2 \param_geometry
+\param intersection_strategy segments intersection strategy
\param robust_policy policy to handle robustness issues
\param turns container which will contain turn points
\param interrupt_policy policy determining if process is stopped
@@ -962,15 +992,17 @@ template
typename AssignPolicy,
typename Geometry1,
typename Geometry2,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename Turns,
typename InterruptPolicy
>
inline void get_turns(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- RobustPolicy const& robust_policy,
- Turns& turns,
- InterruptPolicy& interrupt_policy)
+ Geometry2 const& geometry2,
+ IntersectionStrategy const& intersection_strategy,
+ RobustPolicy const& robust_policy,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy)
{
concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2 const>();
@@ -996,11 +1028,11 @@ inline void get_turns(Geometry1 const& geometry1,
Reverse1, Reverse2,
TurnPolicy
>
- >::type::apply(
- 0, geometry1,
- 1, geometry2,
- robust_policy,
- turns, interrupt_policy);
+ >::type::apply(0, geometry1,
+ 1, geometry2,
+ intersection_strategy,
+ robust_policy,
+ turns, interrupt_policy);
}
#if defined(_MSC_VER)
diff --git a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
index bb82003a23..3244480f48 100644
--- a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
+++ b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
@@ -2,10 +2,11 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015.
-// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
+// 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 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
@@ -71,7 +72,7 @@ struct intersection_segment_segment_point
Segment2 const& segment2,
RobustPolicy const& robust_policy,
OutputIterator out,
- Strategy const& )
+ Strategy const& strategy)
{
typedef typename point_type<PointOut>::type point_type;
@@ -106,16 +107,15 @@ struct intersection_segment_segment_point
>::type
> intersection_return_type;
- typedef strategy::intersection::relate_cartesian_segments
+ typedef policies::relate::segments_intersection_points
<
- policies::relate::segments_intersection_points
- <
- intersection_return_type
- >
- > policy;
+ intersection_return_type
+ > policy_type;
- intersection_return_type is = policy::apply(segment1, segment2,
- robust_policy, pi_rob, pj_rob, qi_rob, qj_rob);
+ intersection_return_type
+ is = strategy.apply(segment1, segment2,
+ policy_type(), robust_policy,
+ pi_rob, pj_rob, qi_rob, qj_rob);
for (std::size_t i = 0; i < is.count; i++)
{
@@ -134,13 +134,14 @@ struct intersection_linestring_linestring_point
<
typename Linestring1, typename Linestring2,
typename RobustPolicy,
- typename OutputIterator, typename Strategy
+ typename OutputIterator,
+ typename Strategy
>
static inline OutputIterator apply(Linestring1 const& linestring1,
Linestring2 const& linestring2,
RobustPolicy const& robust_policy,
OutputIterator out,
- Strategy const& )
+ Strategy const& strategy)
{
typedef typename point_type<PointOut>::type point_type;
@@ -151,7 +152,8 @@ struct intersection_linestring_linestring_point
> turn_info;
std::deque<turn_info> turns;
- geometry::get_intersection_points(linestring1, linestring2, robust_policy, turns);
+ geometry::get_intersection_points(linestring1, linestring2,
+ robust_policy, turns, strategy);
for (typename boost::range_iterator<std::deque<turn_info> const>::type
it = boost::begin(turns); it != boost::end(turns); ++it)
@@ -295,7 +297,7 @@ struct intersection_of_linestring_with_areal
static inline OutputIterator apply(LineString const& linestring, Areal const& areal,
RobustPolicy const& robust_policy,
OutputIterator out,
- Strategy const& )
+ Strategy const& strategy)
{
if (boost::size(linestring) == 0)
{
@@ -325,7 +327,7 @@ struct intersection_of_linestring_with_areal
false,
(OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal),
detail::overlay::assign_null_policy
- >(linestring, areal, robust_policy, turns, policy);
+ >(linestring, areal, strategy, robust_policy, turns, policy);
if (no_crossing_turns_or_empty(turns))
{
@@ -621,7 +623,7 @@ struct intersection_insert
static inline OutputIterator apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
- OutputIterator out, Strategy const& )
+ OutputIterator out, Strategy const& strategy)
{
typedef detail::overlay::turn_info
@@ -635,7 +637,7 @@ struct intersection_insert
geometry::get_turns
<
false, false, detail::overlay::assign_null_policy
- >(geometry1, geometry2, robust_policy, turns, policy);
+ >(geometry1, geometry2, strategy, robust_policy, turns, policy);
for (typename std::vector<turn_info>::const_iterator it
= turns.begin(); it != turns.end(); ++it)
{
@@ -996,7 +998,11 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1,
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- typedef typename Strategy::rescale_policy_type rescale_policy_type;
+ typedef typename geometry::rescale_policy_type
+ <
+ typename geometry::point_type<Geometry1>::type // TODO from both
+ >::type rescale_policy_type;
+
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
@@ -1037,22 +1043,13 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1,
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- typedef typename geometry::rescale_policy_type
- <
- typename geometry::point_type<Geometry1>::type // TODO from both
- >::type rescale_policy_type;
-
- typedef intersection_strategies
+ typedef typename strategy::intersection::services::default_strategy
<
- typename cs_tag<GeometryOut>::type,
- Geometry1,
- Geometry2,
- typename geometry::point_type<GeometryOut>::type,
- rescale_policy_type
- > strategy;
-
+ typename cs_tag<GeometryOut>::type
+ >::type strategy_type;
+
return intersection_insert<GeometryOut>(geometry1, geometry2, out,
- strategy());
+ strategy_type());
}
}} // namespace detail::intersection
diff --git a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
index 34517f6590..a74bb33ba1 100644
--- a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
@@ -1,11 +1,12 @@
// 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.
// 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
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP
@@ -158,11 +159,13 @@ protected:
typename Turns,
typename LinearGeometry1,
typename LinearGeometry2,
+ typename IntersectionStrategy,
typename RobustPolicy
>
static inline void compute_turns(Turns& turns,
LinearGeometry1 const& linear1,
LinearGeometry2 const& linear2,
+ IntersectionStrategy const& strategy,
RobustPolicy const& robust_policy)
{
turns.clear();
@@ -180,7 +183,7 @@ protected:
assign_policy
>,
RobustPolicy
- >::apply(turns, linear1, linear2, interrupt_policy, robust_policy);
+ >::apply(turns, linear1, linear2, interrupt_policy, strategy, robust_policy);
}
@@ -237,7 +240,7 @@ public:
Linear2 const& linear2,
RobustPolicy const& robust_policy,
OutputIterator oit,
- Strategy const& )
+ Strategy const& strategy)
{
typedef typename detail::relate::turns::get_turns
<
@@ -255,7 +258,7 @@ public:
typedef std::vector<turn_info> turns_container;
turns_container turns;
- compute_turns(turns, linear1, linear2, robust_policy);
+ compute_turns(turns, linear1, linear2, strategy, robust_policy);
if ( turns.empty() )
{
diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp
index 09c80025a0..f1af2f1949 100644
--- a/boost/geometry/algorithms/detail/overlay/overlay.hpp
+++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp
@@ -3,10 +3,11 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// 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
@@ -184,7 +185,7 @@ struct overlay
Geometry1 const& geometry1, Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
OutputIterator out,
- Strategy const& ,
+ Strategy const& strategy,
Visitor& visitor)
{
bool const is_empty1 = geometry::is_empty(geometry1);
@@ -233,7 +234,7 @@ std::cout << "get turns" << std::endl;
<
Reverse1, Reverse2,
detail::overlay::assign_null_policy
- >(geometry1, geometry2, robust_policy, turns, policy);
+ >(geometry1, geometry2, strategy, robust_policy, turns, policy);
visitor.visit_turns(1, turns);
@@ -262,6 +263,7 @@ std::cout << "traverse" << std::endl;
traverse<Reverse1, Reverse2, Geometry1, Geometry2, OverlayType>::apply
(
geometry1, geometry2,
+ strategy,
robust_policy,
turns, rings,
clusters,
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
index 156cb54867..a26f54e008 100644
--- a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
@@ -1,12 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015, Oracle and/or its affiliates.
+// 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
// 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_POINTLIKE_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP
@@ -69,12 +70,12 @@ struct point_linear_point
Linear const& linear,
RobustPolicy const&,
OutputIterator oit,
- Strategy const&)
+ Strategy const& strategy)
{
action_selector_pl_l
<
PointOut, OverlayType
- >::apply(point, Policy::apply(point, linear), oit);
+ >::apply(point, Policy::apply(point, linear, strategy), oit);
return oit;
}
};
@@ -95,7 +96,7 @@ struct multipoint_segment_point
Segment const& segment,
RobustPolicy const&,
OutputIterator oit,
- Strategy const&)
+ Strategy const& strategy)
{
for (typename boost::range_iterator<MultiPoint const>::type
it = boost::begin(multipoint);
@@ -105,7 +106,7 @@ struct multipoint_segment_point
action_selector_pl_l
<
PointOut, OverlayType
- >::apply(*it, Policy::apply(*it, segment), oit);
+ >::apply(*it, Policy::apply(*it, segment, strategy), oit);
}
return oit;
@@ -145,11 +146,14 @@ private:
}
};
- template <typename OutputIterator>
+ template <typename OutputIterator, typename Strategy>
class item_visitor_type
{
public:
- item_visitor_type(OutputIterator& oit) : m_oit(oit) {}
+ item_visitor_type(OutputIterator& oit, Strategy const& strategy)
+ : m_oit(oit)
+ , m_strategy(strategy)
+ {}
template <typename Item1, typename Item2>
inline void apply(Item1 const& item1, Item2 const& item2)
@@ -157,11 +161,12 @@ private:
action_selector_pl_l
<
PointOut, overlay_intersection
- >::apply(item1, Policy::apply(item1, item2), m_oit);
+ >::apply(item1, Policy::apply(item1, item2, m_strategy), m_oit);
}
private:
OutputIterator& m_oit;
+ Strategy const& m_strategy;
};
// structs for partition -- end
@@ -189,12 +194,13 @@ private:
Linear const& m_linear;
};
- template <typename OutputIterator>
+ template <typename OutputIterator, typename Strategy>
static inline OutputIterator get_common_points(MultiPoint const& multipoint,
Linear const& linear,
- OutputIterator oit)
+ OutputIterator oit,
+ Strategy const& strategy)
{
- item_visitor_type<OutputIterator> item_visitor(oit);
+ item_visitor_type<OutputIterator, Strategy> item_visitor(oit, strategy);
segment_range rng(linear);
@@ -203,10 +209,9 @@ private:
geometry::model::box
<
typename boost::range_value<MultiPoint>::type
- >,
- expand_box,
- overlaps_box
- >::apply(multipoint, rng, item_visitor);
+ >
+ >::apply(multipoint, rng, item_visitor,
+ expand_box(), overlaps_box());
return oit;
}
@@ -228,7 +233,8 @@ public:
// compute the common points
get_common_points(multipoint, linear,
- std::back_inserter(common_points));
+ std::back_inserter(common_points),
+ strategy);
return multipoint_multipoint_point
<
diff --git a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
index aedf22e1fb..8540ef98a0 100644
--- a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/self_turn_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)
@@ -61,20 +66,25 @@ template
typename Geometry,
typename Turns,
typename TurnPolicy,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename InterruptPolicy
>
struct self_section_visitor
{
Geometry const& m_geometry;
+ IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_rescale_policy;
Turns& m_turns;
InterruptPolicy& m_interrupt_policy;
inline self_section_visitor(Geometry const& g,
- RobustPolicy const& rp,
- Turns& turns, InterruptPolicy& ip)
+ IntersectionStrategy const& is,
+ RobustPolicy const& rp,
+ Turns& turns,
+ InterruptPolicy& ip)
: m_geometry(g)
+ , m_intersection_strategy(is)
, m_rescale_policy(rp)
, m_turns(turns)
, m_interrupt_policy(ip)
@@ -97,6 +107,7 @@ struct self_section_visitor
0, m_geometry, sec1,
0, m_geometry, sec2,
false,
+ m_intersection_strategy,
m_rescale_policy,
m_turns, m_interrupt_policy);
}
@@ -116,9 +127,10 @@ struct self_section_visitor
template<typename TurnPolicy>
struct get_turns
{
- template <typename Geometry, typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename Geometry, typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline bool apply(
Geometry const& geometry,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy)
@@ -142,17 +154,17 @@ struct get_turns
self_section_visitor
<
Geometry,
- Turns, TurnPolicy, RobustPolicy, InterruptPolicy
- > visitor(geometry, robust_policy, turns, interrupt_policy);
+ Turns, TurnPolicy, IntersectionStrategy, RobustPolicy, InterruptPolicy
+ > visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy);
try
{
geometry::partition
<
- box_type,
- detail::section::get_section_box,
- detail::section::overlaps_section_box
- >::apply(sec, visitor);
+ box_type
+ >::apply(sec, visitor,
+ detail::section::get_section_box(),
+ detail::section::overlaps_section_box());
}
catch(self_ip_exception const& )
{
@@ -208,9 +220,10 @@ struct self_get_turn_points
TurnPolicy
>
{
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline bool apply(
Box const& ,
+ Strategy const& ,
RobustPolicy const& ,
Turns& ,
InterruptPolicy& )
@@ -259,6 +272,7 @@ struct self_get_turn_points
\tparam Turns type of intersection container
(e.g. vector of "intersection/turn point"'s)
\param geometry geometry
+ \param strategy strategy to be used
\param robust_policy policy to handle robustness issues
\param turns container which will contain intersection points
\param interrupt_policy policy determining if process is stopped
@@ -268,13 +282,15 @@ template
<
typename AssignPolicy,
typename Geometry,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename Turns,
typename InterruptPolicy
>
inline void self_turns(Geometry const& geometry,
- RobustPolicy const& robust_policy,
- Turns& turns, InterruptPolicy& interrupt_policy)
+ IntersectionStrategy const& strategy,
+ RobustPolicy const& robust_policy,
+ Turns& turns, InterruptPolicy& interrupt_policy)
{
concepts::check<Geometry const>();
@@ -285,7 +301,7 @@ inline void self_turns(Geometry const& geometry,
typename tag<Geometry>::type,
Geometry,
turn_policy
- >::apply(geometry, robust_policy, turns, interrupt_policy);
+ >::apply(geometry, strategy, robust_policy, turns, interrupt_policy);
}
diff --git a/boost/geometry/algorithms/detail/overlay/traversal.hpp b/boost/geometry/algorithms/detail/overlay/traversal.hpp
index 5adc0fcf69..bc828920e9 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal.hpp
@@ -140,10 +140,10 @@ struct traversal
{
for (int i = 0; i < 2; i++)
{
- turn_operation_type& op = turn.operations[i];
- if (op.visited.none())
+ turn_operation_type& turn_op = turn.operations[i];
+ if (turn_op.visited.none())
{
- op.visited.set_visited();
+ turn_op.visited.set_visited();
}
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
index e0dfee19a8..9ab82a77c1 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.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)
@@ -38,6 +42,7 @@ template
typename Geometry2,
typename Turns,
typename Clusters,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename Visitor,
typename Backtrack
@@ -56,12 +61,14 @@ struct traversal_ring_creator
inline traversal_ring_creator(Geometry1 const& geometry1, Geometry2 const& geometry2,
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_geometry1(geometry1)
, m_geometry2(geometry2)
, m_turns(turns)
, m_clusters(clusters)
+ , m_intersection_strategy(intersection_strategy)
, m_robust_policy(robust_policy)
, m_visitor(visitor)
{
@@ -280,7 +287,8 @@ struct traversal_ring_creator
rings, ring, m_turns, start_turn,
m_turns[turn_index].operations[op_index],
traverse_error,
- m_geometry1, m_geometry2, m_robust_policy,
+ m_geometry1, m_geometry2,
+ m_intersection_strategy, m_robust_policy,
state, m_visitor);
}
}
@@ -314,6 +322,7 @@ private:
Geometry2 const& m_geometry2;
Turns& m_turns;
Clusters const& m_clusters;
+ IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_robust_policy;
Visitor& m_visitor;
};
diff --git a/boost/geometry/algorithms/detail/overlay/traverse.hpp b/boost/geometry/algorithms/detail/overlay/traverse.hpp
index f01e50eb03..058f6c9458 100644
--- a/boost/geometry/algorithms/detail/overlay/traverse.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traverse.hpp
@@ -58,6 +58,7 @@ class traverse
public :
template
<
+ typename IntersectionStrategy,
typename RobustPolicy,
typename Turns,
typename Rings,
@@ -66,6 +67,7 @@ public :
>
static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
Turns& turns, Rings& rings,
Clusters& clusters,
@@ -88,10 +90,11 @@ public :
Reverse1, Reverse2, OverlayType,
Geometry1, Geometry2,
Turns, Clusters,
+ IntersectionStrategy,
RobustPolicy, Visitor,
Backtrack
> trav(geometry1, geometry2, turns, clusters,
- robust_policy, visitor);
+ intersection_strategy, robust_policy, visitor);
std::size_t finalized_ring_size = boost::size(rings);
diff --git a/boost/geometry/algorithms/detail/partition.hpp b/boost/geometry/algorithms/detail/partition.hpp
index 8b19add479..12c6a54661 100644
--- a/boost/geometry/algorithms/detail/partition.hpp
+++ b/boost/geometry/algorithms/detail/partition.hpp
@@ -2,10 +2,11 @@
// Copyright (c) 2011-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
@@ -47,13 +48,14 @@ inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)
// Divide forward_range into three subsets: lower, upper and oversized
// (not-fitting)
// (lower == left or bottom, upper == right or top)
-template <typename OverlapsPolicy, typename Box, typename IteratorVector>
+template <typename Box, typename IteratorVector, typename OverlapsPolicy>
inline void divide_into_subsets(Box const& lower_box,
- Box const& upper_box,
- IteratorVector const& input,
- IteratorVector& lower,
- IteratorVector& upper,
- IteratorVector& exceeding)
+ Box const& upper_box,
+ IteratorVector const& input,
+ IteratorVector& lower,
+ IteratorVector& upper,
+ IteratorVector& exceeding,
+ OverlapsPolicy const& overlaps_policy)
{
typedef typename boost::range_iterator
<
@@ -62,8 +64,8 @@ inline void divide_into_subsets(Box const& lower_box,
for(it_type it = boost::begin(input); it != boost::end(input); ++it)
{
- bool const lower_overlapping = OverlapsPolicy::apply(lower_box, **it);
- bool const upper_overlapping = OverlapsPolicy::apply(upper_box, **it);
+ bool const lower_overlapping = overlaps_policy.apply(lower_box, **it);
+ bool const upper_overlapping = overlaps_policy.apply(upper_box, **it);
if (lower_overlapping && upper_overlapping)
{
@@ -87,23 +89,24 @@ inline void divide_into_subsets(Box const& lower_box,
template
<
- typename ExpandPolicy,
typename Box,
- typename IteratorVector
+ typename IteratorVector,
+ typename ExpandPolicy
>
-inline void expand_with_elements(Box& total, IteratorVector const& input)
+inline void expand_with_elements(Box& total, IteratorVector const& input,
+ ExpandPolicy const& expand_policy)
{
typedef typename boost::range_iterator<IteratorVector const>::type it_type;
for(it_type it = boost::begin(input); it != boost::end(input); ++it)
{
- ExpandPolicy::apply(total, **it);
+ expand_policy.apply(total, **it);
}
}
// Match forward_range with itself
-template <typename Policy, typename IteratorVector>
-inline void handle_one(IteratorVector const& input, Policy& policy)
+template <typename IteratorVector, typename VisitPolicy>
+inline void handle_one(IteratorVector const& input, VisitPolicy& visitor)
{
if (boost::size(input) == 0)
{
@@ -118,7 +121,7 @@ inline void handle_one(IteratorVector const& input, Policy& policy)
it_type it2 = it1;
for (++it2; it2 != boost::end(input); ++it2)
{
- policy.apply(**it1, **it2);
+ visitor.apply(**it1, **it2);
}
}
}
@@ -126,13 +129,13 @@ inline void handle_one(IteratorVector const& input, Policy& policy)
// Match forward range 1 with forward range 2
template
<
- typename Policy,
typename IteratorVector1,
- typename IteratorVector2
+ typename IteratorVector2,
+ typename VisitPolicy
>
inline void handle_two(IteratorVector1 const& input1,
- IteratorVector2 const& input2,
- Policy& policy)
+ IteratorVector2 const& input2,
+ VisitPolicy& visitor)
{
typedef typename boost::range_iterator
<
@@ -157,14 +160,14 @@ inline void handle_two(IteratorVector1 const& input1,
it2 != boost::end(input2);
++it2)
{
- policy.apply(**it1, **it2);
+ visitor.apply(**it1, **it2);
}
}
}
template <typename IteratorVector>
inline bool recurse_ok(IteratorVector const& input,
- std::size_t min_elements, std::size_t level)
+ std::size_t min_elements, std::size_t level)
{
return boost::size(input) >= min_elements
&& level < 100;
@@ -172,8 +175,8 @@ inline bool recurse_ok(IteratorVector const& input,
template <typename IteratorVector1, typename IteratorVector2>
inline bool recurse_ok(IteratorVector1 const& input1,
- IteratorVector2 const& input2,
- std::size_t min_elements, std::size_t level)
+ IteratorVector2 const& input2,
+ std::size_t min_elements, std::size_t level)
{
return boost::size(input1) >= min_elements
&& recurse_ok(input2, min_elements, level);
@@ -186,103 +189,114 @@ template
typename IteratorVector3
>
inline bool recurse_ok(IteratorVector1 const& input1,
- IteratorVector2 const& input2,
- IteratorVector3 const& input3,
- std::size_t min_elements, std::size_t level)
+ IteratorVector2 const& input2,
+ IteratorVector3 const& input3,
+ std::size_t min_elements, std::size_t level)
{
return boost::size(input1) >= min_elements
&& recurse_ok(input2, input3, min_elements, level);
}
-template
-<
- int Dimension,
- typename Box,
- typename OverlapsPolicy1,
- typename OverlapsPolicy2,
- typename ExpandPolicy1,
- typename ExpandPolicy2,
- typename VisitBoxPolicy
->
+
+template <int Dimension, typename Box>
class partition_two_ranges;
-template
-<
- int Dimension,
- typename Box,
- typename OverlapsPolicy,
- typename ExpandPolicy,
- typename VisitBoxPolicy
->
+template <int Dimension, typename Box>
class partition_one_range
{
- template <typename IteratorVector>
- static inline Box get_new_box(IteratorVector const& input)
+ template <typename IteratorVector, typename ExpandPolicy>
+ static inline Box get_new_box(IteratorVector const& input,
+ ExpandPolicy const& expand_policy)
{
Box box;
geometry::assign_inverse(box);
- expand_with_elements<ExpandPolicy>(box, input);
+ expand_with_elements(box, input, expand_policy);
return box;
}
- template <typename Policy, typename IteratorVector>
+ template
+ <
+ typename IteratorVector,
+ typename VisitPolicy,
+ typename ExpandPolicy,
+ typename OverlapsPolicy,
+ typename VisitBoxPolicy
+ >
static inline void next_level(Box const& box,
- IteratorVector const& input,
- std::size_t level, std::size_t min_elements,
- Policy& policy, VisitBoxPolicy& box_policy)
+ IteratorVector const& input,
+ 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(input, min_elements, level))
{
partition_one_range
- <
- 1 - Dimension,
- Box,
- OverlapsPolicy,
- ExpandPolicy,
- VisitBoxPolicy
- >::apply(box, input, level + 1, min_elements, policy, box_policy);
+ <
+ 1 - Dimension,
+ Box
+ >::apply(box, input, level + 1, min_elements,
+ visitor, expand_policy, overlaps_policy, box_policy);
}
else
{
- handle_one(input, policy);
+ handle_one(input, visitor);
}
}
// Function to switch to two forward ranges if there are
// geometries exceeding the separation line
- template <typename Policy, typename IteratorVector>
+ template
+ <
+ typename IteratorVector,
+ typename VisitPolicy,
+ typename ExpandPolicy,
+ 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,
- Policy& policy, VisitBoxPolicy& box_policy)
+ VisitPolicy& visitor,
+ ExpandPolicy const& expand_policy,
+ OverlapsPolicy const& overlaps_policy,
+ VisitBoxPolicy& box_policy)
{
if (recurse_ok(input1, input2, min_elements, level))
{
partition_two_ranges
- <
- 1 - Dimension,
- Box,
- OverlapsPolicy, OverlapsPolicy,
- ExpandPolicy, ExpandPolicy,
- VisitBoxPolicy
- >::apply(box, input1, input2, level + 1, min_elements,
- policy, box_policy);
+ <
+ 1 - Dimension, Box
+ >::apply(box, input1, input2, level + 1, min_elements,
+ visitor, expand_policy, overlaps_policy,
+ expand_policy, overlaps_policy, box_policy);
}
else
{
- handle_two(input1, input2, policy);
+ handle_two(input1, input2, visitor);
}
}
public :
- template <typename Policy, typename IteratorVector>
+ template
+ <
+ typename IteratorVector,
+ typename VisitPolicy,
+ typename ExpandPolicy,
+ typename OverlapsPolicy,
+ typename VisitBoxPolicy
+ >
static inline void apply(Box const& box,
- IteratorVector const& input,
- std::size_t level,
- std::size_t min_elements,
- Policy& policy, VisitBoxPolicy& box_policy)
+ IteratorVector const& input,
+ std::size_t level,
+ std::size_t min_elements,
+ VisitPolicy& visitor,
+ ExpandPolicy const& expand_policy,
+ OverlapsPolicy const& overlaps_policy,
+ VisitBoxPolicy& box_policy)
{
box_policy.apply(box, level);
@@ -290,101 +304,121 @@ public :
divide_box<Dimension>(box, lower_box, upper_box);
IteratorVector lower, upper, exceeding;
- divide_into_subsets<OverlapsPolicy>(lower_box, upper_box,
- input, lower, upper, exceeding);
+ divide_into_subsets(lower_box, upper_box,
+ input, lower, upper, exceeding,
+ overlaps_policy);
if (boost::size(exceeding) > 0)
{
// Get the box of exceeding-only
- Box exceeding_box = get_new_box(exceeding);
+ 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,
- policy, box_policy);
+ 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,
- policy, box_policy);
+ visitor, expand_policy, overlaps_policy, box_policy);
next_level2(exceeding_box, exceeding, upper, level, min_elements,
- policy, box_policy);
+ visitor, expand_policy, overlaps_policy, box_policy);
}
// Recursively call operation both parts
- next_level(lower_box, lower, level, min_elements, policy, box_policy);
- next_level(upper_box, upper, level, min_elements, policy, box_policy);
+ 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);
}
};
template
<
int Dimension,
- typename Box,
- typename OverlapsPolicy1,
- typename OverlapsPolicy2,
- typename ExpandPolicy1,
- typename ExpandPolicy2,
- typename VisitBoxPolicy
+ typename Box
>
class partition_two_ranges
{
template
<
- typename Policy,
typename IteratorVector1,
- typename IteratorVector2
+ typename IteratorVector2,
+ typename VisitPolicy,
+ typename ExpandPolicy1,
+ typename OverlapsPolicy1,
+ typename ExpandPolicy2,
+ 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,
- Policy& policy, VisitBoxPolicy& box_policy)
+ 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,
- OverlapsPolicy1,
- OverlapsPolicy2,
- ExpandPolicy1,
- ExpandPolicy2,
- VisitBoxPolicy
+ 1 - Dimension, Box
>::apply(box, input1, input2, level + 1, min_elements,
- policy, box_policy);
+ visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
- template <typename ExpandPolicy, typename IteratorVector>
- static inline Box get_new_box(IteratorVector const& input)
+ template <typename IteratorVector, typename ExpandPolicy>
+ static inline Box get_new_box(IteratorVector const& input,
+ ExpandPolicy const& expand_policy)
{
Box box;
geometry::assign_inverse(box);
- expand_with_elements<ExpandPolicy>(box, input);
+ expand_with_elements(box, input, expand_policy);
return box;
}
- template <typename IteratorVector1, typename IteratorVector2>
+ template
+ <
+ typename IteratorVector1, typename IteratorVector2,
+ typename ExpandPolicy1, typename ExpandPolicy2
+ >
static inline Box get_new_box(IteratorVector1 const& input1,
- IteratorVector2 const& input2)
+ IteratorVector2 const& input2,
+ ExpandPolicy1 const& expand_policy1,
+ ExpandPolicy2 const& expand_policy2)
{
- Box box = get_new_box<ExpandPolicy1>(input1);
- expand_with_elements<ExpandPolicy2>(box, input2);
+ Box box = get_new_box(input1, expand_policy1);
+ expand_with_elements(box, input2, expand_policy2);
return box;
}
public :
template
<
- typename Policy,
typename IteratorVector1,
- typename IteratorVector2
+ typename IteratorVector2,
+ typename VisitPolicy,
+ typename ExpandPolicy1,
+ typename OverlapsPolicy1,
+ typename ExpandPolicy2,
+ 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,
- Policy& policy, VisitBoxPolicy& box_policy)
+ 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);
@@ -393,10 +427,12 @@ public :
IteratorVector1 lower1, upper1, exceeding1;
IteratorVector2 lower2, upper2, exceeding2;
- divide_into_subsets<OverlapsPolicy1>(lower_box, upper_box,
- input1, lower1, upper1, exceeding1);
- divide_into_subsets<OverlapsPolicy2>(lower_box, upper_box,
- input2, lower2, upper2, exceeding2);
+ divide_into_subsets(lower_box, upper_box,
+ input1, lower1, upper1, exceeding1,
+ overlaps_policy1);
+ divide_into_subsets(lower_box, upper_box,
+ input2, lower2, upper2, exceeding2,
+ overlaps_policy2);
if (boost::size(exceeding1) > 0)
{
@@ -404,13 +440,15 @@ public :
if (recurse_ok(exceeding1, exceeding2, min_elements, level))
{
- Box exceeding_box = get_new_box(exceeding1, exceeding2);
+ Box exceeding_box = get_new_box(exceeding1, exceeding2,
+ expand_policy1, expand_policy2);
next_level(exceeding_box, exceeding1, exceeding2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
else
{
- handle_two(exceeding1, exceeding2, policy);
+ handle_two(exceeding1, exceeding2, visitor);
}
// All exceeding from 1 with lower and upper of 2:
@@ -419,16 +457,18 @@ public :
// the same combinations again and again)
if (recurse_ok(lower2, upper2, exceeding1, min_elements, level))
{
- Box exceeding_box = get_new_box<ExpandPolicy1>(exceeding1);
+ Box exceeding_box = get_new_box(exceeding1, expand_policy1);
next_level(exceeding_box, exceeding1, lower2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
next_level(exceeding_box, exceeding1, upper2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
else
{
- handle_two(exceeding1, lower2, policy);
- handle_two(exceeding1, upper2, policy);
+ handle_two(exceeding1, lower2, visitor);
+ handle_two(exceeding1, upper2, visitor);
}
}
@@ -437,36 +477,40 @@ public :
// 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<ExpandPolicy2>(exceeding2);
+ Box exceeding_box = get_new_box(exceeding2, expand_policy2);
next_level(exceeding_box, lower1, exceeding2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
next_level(exceeding_box, upper1, exceeding2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
else
{
- handle_two(lower1, exceeding2, policy);
- handle_two(upper1, exceeding2, policy);
+ handle_two(lower1, exceeding2, visitor);
+ handle_two(upper1, exceeding2, visitor);
}
}
if (recurse_ok(lower1, lower2, min_elements, level))
{
next_level(lower_box, lower1, lower2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
else
{
- handle_two(lower1, lower2, policy);
+ handle_two(lower1, lower2, visitor);
}
if (recurse_ok(upper1, upper2, min_elements, level))
{
next_level(upper_box, upper1, upper2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
else
{
- handle_two(upper1, upper2, policy);
+ handle_two(upper1, upper2, visitor);
}
}
};
@@ -493,46 +537,86 @@ struct include_all_policy
template
<
typename Box,
- typename ExpandPolicy1,
- typename OverlapsPolicy1,
- typename ExpandPolicy2 = ExpandPolicy1,
- typename OverlapsPolicy2 = OverlapsPolicy1,
typename IncludePolicy1 = detail::partition::include_all_policy,
- typename IncludePolicy2 = detail::partition::include_all_policy,
- typename VisitBoxPolicy = detail::partition::visit_no_policy
+ typename IncludePolicy2 = detail::partition::include_all_policy
>
class partition
{
+ static const std::size_t default_min_elements = 16;
+
template
<
- typename ExpandPolicy,
typename IncludePolicy,
typename ForwardRange,
- typename IteratorVector
+ typename IteratorVector,
+ typename ExpandPolicy
>
static inline void expand_to_range(ForwardRange const& forward_range,
- Box& total, IteratorVector& iterator_vector)
+ Box& total,
+ IteratorVector& iterator_vector,
+ ExpandPolicy const& expand_policy)
{
- for(typename boost::range_iterator<ForwardRange const>::type it
- = boost::begin(forward_range);
+ for(typename boost::range_iterator<ForwardRange const>::type
+ it = boost::begin(forward_range);
it != boost::end(forward_range);
++it)
{
if (IncludePolicy::apply(*it))
{
- ExpandPolicy::apply(total, *it);
+ expand_policy.apply(total, *it);
iterator_vector.push_back(it);
}
}
}
-public :
- template <typename ForwardRange, typename VisitPolicy>
+public:
+ template
+ <
+ typename ForwardRange,
+ typename VisitPolicy,
+ typename ExpandPolicy,
+ typename OverlapsPolicy
+ >
static inline void apply(ForwardRange const& forward_range,
- VisitPolicy& visitor,
- std::size_t min_elements = 16,
- VisitBoxPolicy box_visitor = detail::partition::visit_no_policy()
- )
+ 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());
+ }
+
+ template
+ <
+ typename ForwardRange,
+ typename VisitPolicy,
+ typename ExpandPolicy,
+ typename OverlapsPolicy
+ >
+ static inline void 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());
+ }
+
+ template
+ <
+ typename ForwardRange,
+ typename VisitPolicy,
+ typename ExpandPolicy,
+ typename OverlapsPolicy,
+ typename VisitBoxPolicy
+ >
+ static inline void apply(ForwardRange const& forward_range,
+ VisitPolicy& visitor,
+ ExpandPolicy const& expand_policy,
+ OverlapsPolicy const& overlaps_policy,
+ std::size_t min_elements,
+ VisitBoxPolicy box_visitor)
{
typedef typename boost::range_iterator
<
@@ -544,17 +628,14 @@ public :
std::vector<iterator_type> iterator_vector;
Box total;
assign_inverse(total);
- expand_to_range<ExpandPolicy1, IncludePolicy1>(forward_range,
- total, iterator_vector);
+ expand_to_range<IncludePolicy1>(forward_range, total,
+ iterator_vector, expand_policy);
detail::partition::partition_one_range
<
- 0, Box,
- OverlapsPolicy1,
- ExpandPolicy1,
- VisitBoxPolicy
+ 0, Box
>::apply(total, iterator_vector, 0, min_elements,
- visitor, box_visitor);
+ visitor, expand_policy, overlaps_policy, box_visitor);
}
else
{
@@ -575,15 +656,88 @@ public :
<
typename ForwardRange1,
typename ForwardRange2,
- typename VisitPolicy
+ typename VisitPolicy,
+ typename ExpandPolicy1,
+ typename OverlapsPolicy1
+ >
+ static inline void 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());
+ }
+
+ template
+ <
+ typename ForwardRange1,
+ typename ForwardRange2,
+ typename VisitPolicy,
+ typename ExpandPolicy1,
+ typename OverlapsPolicy1,
+ typename ExpandPolicy2,
+ typename OverlapsPolicy2
+ >
+ static inline void apply(ForwardRange1 const& forward_range1,
+ ForwardRange2 const& forward_range2,
+ VisitPolicy& visitor,
+ ExpandPolicy1 const& expand_policy1,
+ OverlapsPolicy1 const& overlaps_policy1,
+ 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());
+ }
+
+ template
+ <
+ typename ForwardRange1,
+ typename ForwardRange2,
+ typename VisitPolicy,
+ typename ExpandPolicy1,
+ typename OverlapsPolicy1,
+ typename ExpandPolicy2,
+ typename OverlapsPolicy2
+ >
+ static inline void apply(ForwardRange1 const& forward_range1,
+ ForwardRange2 const& forward_range2,
+ VisitPolicy& visitor,
+ ExpandPolicy1 const& expand_policy1,
+ OverlapsPolicy1 const& overlaps_policy1,
+ ExpandPolicy2 const& expand_policy2,
+ 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());
+ }
+
+ template
+ <
+ typename ForwardRange1,
+ typename ForwardRange2,
+ typename VisitPolicy,
+ typename ExpandPolicy1,
+ typename OverlapsPolicy1,
+ typename ExpandPolicy2,
+ typename OverlapsPolicy2,
+ typename VisitBoxPolicy
>
static inline void apply(ForwardRange1 const& forward_range1,
- ForwardRange2 const& forward_range2,
- VisitPolicy& visitor,
- std::size_t min_elements = 16,
- VisitBoxPolicy box_visitor
- = detail::partition::visit_no_policy()
- )
+ ForwardRange2 const& forward_range2,
+ VisitPolicy& visitor,
+ ExpandPolicy1 const& expand_policy1,
+ OverlapsPolicy1 const& overlaps_policy1,
+ ExpandPolicy2 const& expand_policy2,
+ OverlapsPolicy2 const& overlaps_policy2,
+ std::size_t min_elements,
+ VisitBoxPolicy box_visitor)
{
typedef typename boost::range_iterator
<
@@ -602,17 +756,18 @@ public :
std::vector<iterator_type2> iterator_vector2;
Box total;
assign_inverse(total);
- expand_to_range<ExpandPolicy1, IncludePolicy1>(forward_range1,
- total, iterator_vector1);
- expand_to_range<ExpandPolicy2, IncludePolicy2>(forward_range2,
- total, iterator_vector2);
+ expand_to_range<IncludePolicy1>(forward_range1, total,
+ iterator_vector1, expand_policy1);
+ expand_to_range<IncludePolicy2>(forward_range2, total,
+ iterator_vector2, expand_policy2);
detail::partition::partition_two_ranges
<
- 0, Box, OverlapsPolicy1, OverlapsPolicy2,
- ExpandPolicy1, ExpandPolicy2, VisitBoxPolicy
+ 0, Box
>::apply(total, iterator_vector1, iterator_vector2,
- 0, min_elements, visitor, box_visitor);
+ 0, min_elements, visitor, expand_policy1,
+ overlaps_policy1, expand_policy2, overlaps_policy2,
+ box_visitor);
}
else
{
diff --git a/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
index a74954326b..800fbb2e96 100644
--- a/boost/geometry/algorithms/detail/relate/areal_areal.hpp
+++ b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// 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
@@ -40,12 +40,21 @@ namespace detail { namespace relate {
// Use the rtree in this case!
// may be used to set EI and EB for an Areal geometry for which no turns were generated
-template <typename OtherAreal, typename Result, bool TransposeResult>
+template
+<
+ typename OtherAreal,
+ typename Result,
+ typename PointInArealStrategy,
+ bool TransposeResult
+>
class no_turns_aa_pred
{
public:
- no_turns_aa_pred(OtherAreal const& other_areal, Result & res)
+ no_turns_aa_pred(OtherAreal const& other_areal,
+ Result & res,
+ PointInArealStrategy const& point_in_areal_strategy)
: m_result(res)
+ , m_point_in_areal_strategy(point_in_areal_strategy)
, m_other_areal(other_areal)
, m_flags(0)
{
@@ -68,6 +77,8 @@ public:
template <typename Areal>
bool operator()(Areal const& areal)
{
+ using detail::within::point_in_geometry;
+
// if those flags are set nothing will change
if ( m_flags == 3 )
{
@@ -87,7 +98,9 @@ public:
// check if the areal is inside the other_areal
// TODO: This is O(N)
// Run in a loop O(NM) - optimize!
- int const pig = detail::within::point_in_geometry(pt, m_other_areal);
+ int const pig = point_in_geometry(pt,
+ m_other_areal,
+ m_point_in_areal_strategy);
//BOOST_GEOMETRY_ASSERT( pig != 0 );
// inside
@@ -119,7 +132,9 @@ public:
// TODO: O(N)
// Optimize!
- int const hpig = detail::within::point_in_geometry(range::front(range_ref), m_other_areal);
+ int const hpig = point_in_geometry(range::front(range_ref),
+ m_other_areal,
+ m_point_in_areal_strategy);
// hole outside
if ( hpig < 0 )
@@ -155,7 +170,9 @@ public:
// TODO: O(N)
// Optimize!
- int const hpig = detail::within::point_in_geometry(range::front(range_ref), m_other_areal);
+ int const hpig = point_in_geometry(range::front(range_ref),
+ m_other_areal,
+ m_point_in_areal_strategy);
// hole inside
if ( hpig > 0 )
@@ -174,6 +191,7 @@ public:
private:
Result & m_result;
+ PointInArealStrategy const& m_point_in_areal_strategy;
OtherAreal const& m_other_areal;
int m_flags;
};
@@ -191,8 +209,10 @@ struct areal_areal
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type;
- template <typename Result>
- static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)
+ template <typename Result, typename IntersectionStrategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ IntersectionStrategy const& intersection_strategy)
{
// TODO: If Areal geometry may have infinite size, change the following line:
@@ -208,16 +228,31 @@ struct areal_areal
interrupt_policy_areal_areal<Result> interrupt_policy(geometry1, geometry2, result);
- turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy);
+ turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
- no_turns_aa_pred<Geometry2, Result, false> pred1(geometry2, result);
+ typedef typename IntersectionStrategy::template point_in_geometry_strategy
+ <
+ Geometry1, Geometry2
+ >::type point_in_areal_strategy12_type;
+ point_in_areal_strategy12_type point_in_areal_strategy12
+ = intersection_strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>();
+ typedef typename IntersectionStrategy::template point_in_geometry_strategy
+ <
+ Geometry2, Geometry1
+ >::type point_in_areal_strategy21_type;
+ point_in_areal_strategy21_type point_in_areal_strategy21
+ = intersection_strategy.template get_point_in_geometry_strategy<Geometry2, Geometry1>();
+
+ no_turns_aa_pred<Geometry2, Result, point_in_areal_strategy12_type, false>
+ pred1(geometry2, result, point_in_areal_strategy12);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
- no_turns_aa_pred<Geometry1, Result, true> pred2(geometry1, result);
+ no_turns_aa_pred<Geometry1, Result, point_in_areal_strategy21_type, true>
+ pred2(geometry1, result, point_in_areal_strategy21);
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
@@ -256,7 +291,8 @@ struct areal_areal
{
// analyse rings for which turns were not generated
// or only i/i or u/u was generated
- uncertain_rings_analyser<0, Result, Geometry1, Geometry2> rings_analyser(result, geometry1, geometry2);
+ uncertain_rings_analyser<0, Result, Geometry1, Geometry2, point_in_areal_strategy12_type>
+ rings_analyser(result, geometry1, geometry2, point_in_areal_strategy12);
analyse_uncertain_rings<0>::apply(rings_analyser, turns.begin(), turns.end());
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
@@ -295,7 +331,8 @@ struct areal_areal
{
// analyse rings for which turns were not generated
// or only i/i or u/u was generated
- uncertain_rings_analyser<1, Result, Geometry2, Geometry1> rings_analyser(result, geometry2, geometry1);
+ uncertain_rings_analyser<1, Result, Geometry2, Geometry1, point_in_areal_strategy21_type>
+ rings_analyser(result, geometry2, geometry1, point_in_areal_strategy21);
analyse_uncertain_rings<1>::apply(rings_analyser, turns.begin(), turns.end());
//if ( result.interrupt )
@@ -565,7 +602,14 @@ struct areal_areal
analyser.apply(res);
}
- template <std::size_t OpId, typename Result, typename Geometry, typename OtherGeometry>
+ template
+ <
+ std::size_t OpId,
+ typename Result,
+ typename Geometry,
+ typename OtherGeometry,
+ typename PointInArealStrategy
+ >
class uncertain_rings_analyser
{
static const bool transpose_result = OpId != 0;
@@ -574,10 +618,13 @@ struct areal_areal
public:
inline uncertain_rings_analyser(Result & result,
Geometry const& geom,
- OtherGeometry const& other_geom)
- : geometry(geom), other_geometry(other_geom)
+ OtherGeometry const& other_geom,
+ PointInArealStrategy const& point_in_areal_strategy)
+ : geometry(geom)
+ , other_geometry(other_geom)
, interrupt(result.interrupt) // just in case, could be false as well
, m_result(result)
+ , m_point_in_areal_strategy(point_in_areal_strategy)
, m_flags(0)
{
// check which relations must be analysed
@@ -624,7 +671,10 @@ struct areal_areal
// TODO: optimize! e.g. use spatial index
// O(N) - running it in a loop gives O(NM)
- int const pig = detail::within::point_in_geometry(range::front(range_ref), other_geometry);
+ using detail::within::point_in_geometry;
+ int const pig = point_in_geometry(range::front(range_ref),
+ other_geometry,
+ m_point_in_areal_strategy);
//BOOST_GEOMETRY_ASSERT(pig != 0);
if ( pig > 0 )
@@ -713,6 +763,7 @@ struct areal_areal
private:
Result & m_result;
+ PointInArealStrategy const& m_point_in_areal_strategy;
int m_flags;
};
diff --git a/boost/geometry/algorithms/detail/relate/implementation.hpp b/boost/geometry/algorithms/detail/relate/implementation.hpp
index a6f1545ed1..3bd0f806c1 100644
--- a/boost/geometry/algorithms/detail/relate/implementation.hpp
+++ b/boost/geometry/algorithms/detail/relate/implementation.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// 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
@@ -25,6 +25,9 @@
#include <boost/geometry/algorithms/detail/relate/linear_areal.hpp>
#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/within.hpp>
+
namespace boost { namespace geometry {
diff --git a/boost/geometry/algorithms/detail/relate/interface.hpp b/boost/geometry/algorithms/detail/relate/interface.hpp
index 95d452931c..3575fe2bc4 100644
--- a/boost/geometry/algorithms/detail/relate/interface.hpp
+++ b/boost/geometry/algorithms/detail/relate/interface.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// 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
@@ -29,6 +29,7 @@
#include <boost/geometry/algorithms/not_implemented.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 {
@@ -186,18 +187,59 @@ struct result_handler_type<Geometry1, Geometry2, StaticSequence, true>
> type;
};
+
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
+namespace resolve_strategy {
+
+struct relate
+{
+ template <typename Geometry1, typename Geometry2, typename ResultHandler, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ ResultHandler & handler,
+ Strategy const& strategy)
+ {
+ dispatch::relate
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, handler, strategy);
+ }
+
+ template <typename Geometry1, typename Geometry2, typename ResultHandler>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ ResultHandler & handler,
+ default_strategy)
+ {
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
+ dispatch::relate
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, handler, strategy_type());
+ }
+};
+
+} // resolve_strategy
+
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct relate
{
- template <typename Mask>
+ template <typename Mask, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- Mask const& mask)
+ Mask const& mask,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
@@ -210,11 +252,7 @@ struct relate
Mask
>::type handler(mask);
- dispatch::relate
- <
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, handler);
+ resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy);
return handler.result();
}
@@ -223,60 +261,64 @@ struct relate
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct relate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
- template <typename Mask>
+ template <typename Mask, typename Strategy>
struct visitor : boost::static_visitor<bool>
{
Geometry2 const& m_geometry2;
Mask const& m_mask;
+ Strategy const& m_strategy;
- visitor(Geometry2 const& geometry2, Mask const& mask)
- : m_geometry2(geometry2), m_mask(mask) {}
+ visitor(Geometry2 const& geometry2, Mask const& mask, Strategy const& strategy)
+ : m_geometry2(geometry2), m_mask(mask), m_strategy(strategy) {}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
return relate<Geometry1, Geometry2>
- ::apply(geometry1, m_geometry2, m_mask);
+ ::apply(geometry1, m_geometry2, m_mask, m_strategy);
}
};
- template <typename Mask>
+ template <typename Mask, typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
- Mask const& mask)
+ Mask const& mask,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Mask>(geometry2, mask), geometry1);
+ return boost::apply_visitor(visitor<Mask, Strategy>(geometry2, mask, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct relate<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
- template <typename Mask>
+ template <typename Mask, typename Strategy>
struct visitor : boost::static_visitor<bool>
{
Geometry1 const& m_geometry1;
Mask const& m_mask;
+ Strategy const& m_strategy;
- visitor(Geometry1 const& geometry1, Mask const& mask)
- : m_geometry1(geometry1), m_mask(mask) {}
+ visitor(Geometry1 const& geometry1, Mask const& mask, Strategy const& strategy)
+ : m_geometry1(geometry1), m_mask(mask), m_strategy(strategy) {}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
return relate<Geometry1, Geometry2>
- ::apply(m_geometry1, geometry2, m_mask);
+ ::apply(m_geometry1, geometry2, m_mask, m_strategy);
}
};
- template <typename Mask>
+ template <typename Mask, typename Strategy>
static inline bool
apply(Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Mask const& mask)
+ Mask const& mask,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Mask>(geometry1, mask), geometry2);
+ return boost::apply_visitor(visitor<Mask, Strategy>(geometry1, mask, strategy), geometry2);
}
};
@@ -289,30 +331,32 @@ struct relate<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
- template <typename Mask>
+ template <typename Mask, typename Strategy>
struct visitor : boost::static_visitor<bool>
{
Mask const& m_mask;
+ Strategy const& m_strategy;
- visitor(Mask const& mask)
- : m_mask(mask) {}
+ visitor(Mask const& mask, Strategy const& strategy)
+ : m_mask(mask), m_strategy(strategy) {}
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return relate<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, m_mask);
+ ::apply(geometry1, geometry2, m_mask, m_strategy);
}
};
- template <typename Mask>
+ template <typename Mask, typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Mask const& mask)
+ Mask const& mask,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Mask>(mask), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Mask, Strategy>(mask, strategy), geometry1, geometry2);
}
};
@@ -324,6 +368,35 @@ struct relate<
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Mask An intersection model Mask type.
+\tparam Strategy \tparam_strategy{Relate}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param mask An intersection model mask object.
+\param strategy \param_strategy{relate}
+\return true if the relation is compatible with the mask, false otherwise.
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/relate.qbk]}
+ */
+template <typename Geometry1, typename Geometry2, typename Mask, typename Strategy>
+inline bool relate(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Mask const& mask,
+ Strategy const& strategy)
+{
+ return resolve_variant::relate
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, mask, strategy);
+}
+
+/*!
+\brief Checks relation between a pair of geometries defined by a mask.
+\ingroup relate
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Mask An intersection model Mask type.
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param mask An intersection model mask object.
@@ -340,7 +413,7 @@ inline bool relate(Geometry1 const& geometry1,
<
Geometry1,
Geometry2
- >::apply(geometry1, geometry2, mask);
+ >::apply(geometry1, geometry2, mask, default_strategy());
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
index 58ba7bd1af..f1b4fdf81a 100644
--- a/boost/geometry/algorithms/detail/relate/linear_areal.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// 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
@@ -46,15 +46,24 @@ namespace detail { namespace relate {
// Use the rtree in this case!
// may be used to set IE and BE for a Linear geometry for which no turns were generated
-template <typename Geometry2, typename Result, typename BoundaryChecker, bool TransposeResult>
+template
+<
+ typename Geometry2,
+ typename Result,
+ typename PointInArealStrategy,
+ typename BoundaryChecker,
+ bool TransposeResult
+>
class no_turns_la_linestring_pred
{
public:
no_turns_la_linestring_pred(Geometry2 const& geometry2,
Result & res,
+ PointInArealStrategy const& point_in_areal_strategy,
BoundaryChecker const& boundary_checker)
: m_geometry2(geometry2)
, m_result(res)
+ , m_point_in_areal_strategy(point_in_areal_strategy)
, m_boundary_checker(boundary_checker)
, m_interrupt_flags(0)
{
@@ -98,7 +107,9 @@ public:
return false;
}
- int const pig = detail::within::point_in_geometry(range::front(linestring), m_geometry2);
+ int const pig = detail::within::point_in_geometry(range::front(linestring),
+ m_geometry2,
+ m_point_in_areal_strategy);
//BOOST_GEOMETRY_ASSERT_MSG(pig != 0, "There should be no IPs");
if ( pig > 0 )
@@ -138,6 +149,7 @@ public:
private:
Geometry2 const& m_geometry2;
Result & m_result;
+ PointInArealStrategy const& m_point_in_areal_strategy;
BoundaryChecker const& m_boundary_checker;
unsigned m_interrupt_flags;
};
@@ -225,8 +237,10 @@ struct linear_areal
>
{};
- template <typename Result>
- static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)
+ template <typename Result, typename IntersectionStrategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ IntersectionStrategy const& intersection_strategy)
{
// TODO: If Areal geometry may have infinite size, change the following line:
@@ -242,7 +256,7 @@ struct linear_areal
interrupt_policy_linear_areal<Geometry2, Result> interrupt_policy(geometry2, result);
- turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy);
+ turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
@@ -251,9 +265,13 @@ struct linear_areal
<
Geometry2,
Result,
+ typename IntersectionStrategy::template point_in_geometry_strategy<Geometry1, Geometry2>::type,
boundary_checker<Geometry1>,
TransposeResult
- > pred1(geometry2, result, boundary_checker1);
+ > pred1(geometry2,
+ result,
+ intersection_strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>(),
+ boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
@@ -279,7 +297,8 @@ struct linear_areal
analyse_each_turn(result, analyser,
turns.begin(), turns.end(),
geometry1, geometry2,
- boundary_checker1);
+ boundary_checker1,
+ intersection_strategy.get_side_strategy());
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
@@ -615,11 +634,13 @@ struct linear_areal
typename TurnIt,
typename Geometry,
typename OtherGeometry,
- typename BoundaryChecker>
+ typename BoundaryChecker,
+ typename SideStrategy>
void apply(Result & res, TurnIt it,
Geometry const& geometry,
OtherGeometry const& other_geometry,
- BoundaryChecker const& boundary_checker)
+ BoundaryChecker const& boundary_checker,
+ SideStrategy const& side_strategy)
{
overlay::operation_type op = it->operations[op_id].operation;
@@ -856,7 +877,8 @@ struct linear_areal
bool const from_inside = first_point
&& calculate_from_inside(geometry,
other_geometry,
- *it);
+ *it,
+ side_strategy);
if ( from_inside )
update<interior, interior, '1', TransposeResult>(res);
@@ -956,7 +978,8 @@ struct linear_areal
bool const first_from_inside = first_point
&& calculate_from_inside(geometry,
other_geometry,
- *it);
+ *it,
+ side_strategy);
if ( first_from_inside )
{
update<interior, interior, '1', TransposeResult>(res);
@@ -1144,10 +1167,11 @@ struct linear_areal
// check if the passed turn's segment of Linear geometry arrived
// from the inside or the outside of the Areal geometry
- template <typename Turn>
+ template <typename Turn, typename SideStrategy>
static inline bool calculate_from_inside(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- Turn const& turn)
+ Turn const& turn,
+ SideStrategy const& side_strategy)
{
typedef typename cs_tag<typename Turn::point_type>::type cs_tag;
@@ -1194,16 +1218,18 @@ struct linear_areal
boost::end(range2));
// Will this sequence of points be always correct?
- overlay::side_calculator<cs_tag, point1_type, point2_type> side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it);
+ overlay::side_calculator<cs_tag, point1_type, point2_type, SideStrategy>
+ side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, side_strategy);
return calculate_from_inside_sides(side_calc);
}
else
{
- point1_type new_qj;
+ point2_type new_qj;
geometry::convert(turn.point, new_qj);
- overlay::side_calculator<cs_tag, point1_type, point2_type> side_calc(qi_conv, new_pj, pi, qi, new_qj, qj);
+ overlay::side_calculator<cs_tag, point1_type, point2_type, SideStrategy>
+ side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, side_strategy);
return calculate_from_inside_sides(side_calc);
}
@@ -1270,13 +1296,15 @@ struct linear_areal
typename Analyser,
typename Geometry,
typename OtherGeometry,
- typename BoundaryChecker>
+ typename BoundaryChecker,
+ typename SideStrategy>
static inline void analyse_each_turn(Result & res,
Analyser & analyser,
TurnIt first, TurnIt last,
Geometry const& geometry,
OtherGeometry const& other_geometry,
- BoundaryChecker const& boundary_checker)
+ BoundaryChecker const& boundary_checker,
+ SideStrategy const& side_strategy)
{
if ( first == last )
return;
@@ -1285,7 +1313,8 @@ struct linear_areal
{
analyser.apply(res, it,
geometry, other_geometry,
- boundary_checker);
+ boundary_checker,
+ side_strategy);
if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) )
return;
@@ -1420,10 +1449,12 @@ struct areal_linear
static const bool interruption_enabled = linear_areal_type::interruption_enabled;
- template <typename Result>
- static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)
+ template <typename Result, typename IntersectionStrategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ IntersectionStrategy const& intersection_strategy)
{
- linear_areal_type::apply(geometry2, geometry1, result);
+ linear_areal_type::apply(geometry2, geometry1, result, intersection_strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
index 7a3f373e03..520f2bd775 100644
--- a/boost/geometry/algorithms/detail/relate/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
@@ -2,15 +2,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// 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
// Use, modification and distribution is subject to the 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_LINEAR_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP
@@ -119,8 +119,10 @@ struct linear_linear
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type;
- template <typename Result>
- static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)
+ template <typename Result, typename IntersectionStrategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ IntersectionStrategy const& intersection_strategy)
{
// The result should be FFFFFFFFF
relate::set<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T
@@ -138,7 +140,7 @@ struct linear_linear
Geometry1,
Geometry2,
detail::get_turns::get_turn_info_type<Geometry1, Geometry2, turns::assign_policy<true> >
- >::apply(turns, geometry1, geometry2, interrupt_policy);
+ >::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
diff --git a/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
index be08016a16..a0c6c0d49b 100644
--- a/boost/geometry/algorithms/detail/relate/point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// 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
@@ -37,10 +37,10 @@ struct point_geometry
static const bool interruption_enabled = true;
- template <typename Result>
- static inline void apply(Point const& point, Geometry const& geometry, Result & result)
+ template <typename Result, typename Strategy>
+ static inline void apply(Point const& point, Geometry const& geometry, Result & result, Strategy const& strategy)
{
- int pig = detail::within::point_in_geometry(point, geometry);
+ int pig = detail::within::point_in_geometry(point, geometry, strategy);
if ( pig > 0 ) // within
{
@@ -95,10 +95,10 @@ struct geometry_point
static const bool interruption_enabled = true;
- template <typename Result>
- static inline void apply(Geometry const& geometry, Point const& point, Result & result)
+ template <typename Result, typename Strategy>
+ static inline void apply(Geometry const& geometry, Point const& point, Result & result, Strategy const& strategy)
{
- point_geometry<Point, Geometry, true>::apply(point, geometry, result);
+ point_geometry<Point, Geometry, true>::apply(point, geometry, result, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/relate/point_point.hpp b/boost/geometry/algorithms/detail/relate/point_point.hpp
index e55be08225..b41d346f0b 100644
--- a/boost/geometry/algorithms/detail/relate/point_point.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_point.hpp
@@ -2,15 +2,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// 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, 2014, 2017.
+// Modifications copyright (c) 2013-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_POINT_POINT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP
@@ -35,8 +35,10 @@ struct point_point
{
static const bool interruption_enabled = false;
- template <typename Result>
- static inline void apply(Point1 const& point1, Point2 const& point2, Result & result)
+ template <typename Result, typename Strategy>
+ static inline void apply(Point1 const& point1, Point2 const& point2,
+ Result & result,
+ Strategy const& /*strategy*/)
{
bool equal = detail::equals::equals_point_point(point1, point2);
if ( equal )
@@ -86,8 +88,10 @@ struct point_multipoint
{
static const bool interruption_enabled = false;
- template <typename Result>
- static inline void apply(Point const& point, MultiPoint const& multi_point, Result & result)
+ template <typename Result, typename Strategy>
+ static inline void apply(Point const& point, MultiPoint const& multi_point,
+ Result & result,
+ Strategy const& /*strategy*/)
{
if ( boost::empty(multi_point) )
{
@@ -122,10 +126,12 @@ struct multipoint_point
{
static const bool interruption_enabled = false;
- template <typename Result>
- static inline void apply(MultiPoint const& multi_point, Point const& point, Result & result)
+ template <typename Result, typename Strategy>
+ static inline void apply(MultiPoint const& multi_point, Point const& point,
+ Result & result,
+ Strategy const& strategy)
{
- point_multipoint<Point, MultiPoint, true>::apply(point, multi_point, result);
+ point_multipoint<Point, MultiPoint, true>::apply(point, multi_point, result, strategy);
}
};
@@ -134,8 +140,10 @@ struct multipoint_multipoint
{
static const bool interruption_enabled = true;
- template <typename Result>
- static inline void apply(MultiPoint1 const& multi_point1, MultiPoint2 const& multi_point2, Result & result)
+ template <typename Result, typename Strategy>
+ static inline void apply(MultiPoint1 const& multi_point1, MultiPoint2 const& multi_point2,
+ Result & result,
+ Strategy const& /*strategy*/)
{
{
// TODO: throw on empty input?
diff --git a/boost/geometry/algorithms/detail/relate/relate_impl.hpp b/boost/geometry/algorithms/detail/relate/relate_impl.hpp
index e8e422993d..2ec2361c03 100644
--- a/boost/geometry/algorithms/detail/relate/relate_impl.hpp
+++ b/boost/geometry/algorithms/detail/relate/relate_impl.hpp
@@ -57,7 +57,8 @@ struct relate_impl
implemented_tag
>::type
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
typename detail::relate::result_handler_type
<
@@ -66,7 +67,7 @@ struct relate_impl
typename StaticMaskTrait<Geometry1, Geometry2>::type
>::type handler;
- dispatch::relate<Geometry1, Geometry2>::apply(g1, g2, handler);
+ dispatch::relate<Geometry1, Geometry2>::apply(g1, g2, handler, strategy);
return handler.result();
}
diff --git a/boost/geometry/algorithms/detail/relate/result.hpp b/boost/geometry/algorithms/detail/relate/result.hpp
index a92badf65b..07287dc625 100644
--- a/boost/geometry/algorithms/detail/relate/result.hpp
+++ b/boost/geometry/algorithms/detail/relate/result.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2016.
// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.
@@ -24,6 +25,7 @@
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/next.hpp>
#include <boost/static_assert.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits/integral_constant.hpp>
@@ -266,7 +268,7 @@ private:
|| ( c >= '0' && c <= '9' );
if ( !is_valid )
{
- throw geometry::invalid_input_exception();
+ BOOST_THROW_EXCEPTION(geometry::invalid_input_exception());
}
}
diff --git a/boost/geometry/algorithms/detail/relate/turns.hpp b/boost/geometry/algorithms/detail/relate/turns.hpp
index 09d74dec3a..6fa05eaf21 100644
--- a/boost/geometry/algorithms/detail/relate/turns.hpp
+++ b/boost/geometry/algorithms/detail/relate/turns.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// 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
@@ -75,28 +75,35 @@ struct get_turns
{
detail::get_turns::no_interrupt_policy interrupt_policy;
- apply(turns, geometry1, geometry2, interrupt_policy);
+ typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<Geometry1>::type
+ >::type intersection_strategy;
+
+ apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy);
}
- template <typename Turns, typename InterruptPolicy>
+ template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy>
static inline void apply(Turns & turns,
Geometry1 const& geometry1,
Geometry2 const& geometry2,
- InterruptPolicy & interrupt_policy)
+ InterruptPolicy & interrupt_policy,
+ IntersectionStrategy const& intersection_strategy)
{
RobustPolicy robust_policy = geometry::get_rescale_policy
<
RobustPolicy
>(geometry1, geometry2);
- apply(turns, geometry1, geometry2, interrupt_policy, robust_policy);
+ apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy, robust_policy);
}
- template <typename Turns, typename InterruptPolicy>
+ template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy>
static inline void apply(Turns & turns,
Geometry1 const& geometry1,
Geometry2 const& geometry2,
InterruptPolicy & interrupt_policy,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy)
{
static const bool reverse1 = detail::overlay::do_reverse
@@ -119,7 +126,8 @@ struct get_turns
reverse2,
GetTurnPolicy
>::apply(0, geometry1, 1, geometry2,
- robust_policy, turns, interrupt_policy);
+ intersection_strategy, robust_policy,
+ turns, interrupt_policy);
}
};
diff --git a/boost/geometry/algorithms/detail/relation/interface.hpp b/boost/geometry/algorithms/detail/relation/interface.hpp
index e9a9474551..83d27ed72f 100644
--- a/boost/geometry/algorithms/detail/relation/interface.hpp
+++ b/boost/geometry/algorithms/detail/relation/interface.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// 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
@@ -35,16 +35,16 @@ struct result_handler_type<Geometry1, Geometry2, geometry::de9im::matrix, false>
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
-
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2>
struct relation
{
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
static inline Matrix apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2)
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
@@ -57,11 +57,7 @@ struct relation
Matrix
>::type handler;
- dispatch::relate
- <
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, handler);
+ resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy);
return handler.result();
}
@@ -70,56 +66,60 @@ struct relation
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct relation<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
struct visitor : boost::static_visitor<Matrix>
{
Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
- visitor(Geometry2 const& geometry2)
- : m_geometry2(geometry2) {}
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
+ : m_geometry2(geometry2), m_strategy(strategy) {}
template <typename Geometry1>
Matrix operator()(Geometry1 const& geometry1) const
{
return relation<Geometry1, Geometry2>
- ::template apply<Matrix>(geometry1, m_geometry2);
+ ::template apply<Matrix>(geometry1, m_geometry2, m_strategy);
}
};
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
static inline Matrix
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2)
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Matrix>(geometry2), geometry1);
+ return boost::apply_visitor(visitor<Matrix, Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct relation<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
struct visitor : boost::static_visitor<Matrix>
{
Geometry1 const& m_geometry1;
+ Strategy const& m_strategy;
- visitor(Geometry1 const& geometry1)
- : m_geometry1(geometry1) {}
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
+ : m_geometry1(geometry1), m_strategy(strategy) {}
template <typename Geometry2>
Matrix operator()(Geometry2 const& geometry2) const
{
return relation<Geometry1, Geometry2>
- ::template apply<Matrix>(m_geometry1, geometry2);
+ ::template apply<Matrix>(m_geometry1, geometry2, m_strategy);
}
};
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
static inline Matrix
apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Matrix>(geometry1), geometry2);
+ return boost::apply_visitor(visitor<Matrix, Strategy>(geometry1, strategy), geometry2);
}
};
@@ -134,24 +134,30 @@ struct relation
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
struct visitor : boost::static_visitor<Matrix>
{
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy)
+ : m_strategy(strategy) {}
+
template <typename Geometry1, typename Geometry2>
Matrix operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return relation<Geometry1, Geometry2>
- ::template apply<Matrix>(geometry1, geometry2);
+ ::template apply<Matrix>(geometry1, geometry2, m_strategy);
}
};
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
static inline Matrix
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Matrix>(), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Matrix, Strategy>(strategy), geometry1, geometry2);
}
};
@@ -163,6 +169,33 @@ struct relation
\ingroup relation
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Relation}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{relation}
+\return The DE-9IM matrix expressing the relation between geometries.
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/relation.qbk]}
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline de9im::matrix relation(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ return resolve_variant::relation
+ <
+ Geometry1,
+ Geometry2
+ >::template apply<de9im::matrix>(geometry1, geometry2, strategy);
+}
+
+
+/*!
+\brief Calculates the relation between a pair of geometries as defined in DE-9IM.
+\ingroup relation
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return The DE-9IM matrix expressing the relation between geometries.
@@ -177,7 +210,7 @@ inline de9im::matrix relation(Geometry1 const& geometry1,
<
Geometry1,
Geometry2
- >::template apply<de9im::matrix>(geometry1, geometry2);
+ >::template apply<de9im::matrix>(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/throw_on_empty_input.hpp b/boost/geometry/algorithms/detail/throw_on_empty_input.hpp
index 2f82e1a8bd..3d45a46d16 100644
--- a/boost/geometry/algorithms/detail/throw_on_empty_input.hpp
+++ b/boost/geometry/algorithms/detail/throw_on_empty_input.hpp
@@ -3,6 +3,7 @@
// 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) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
@@ -16,9 +17,13 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP
+
#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
+#include <boost/throw_exception.hpp>
+
+
// BSG 2012-02-06: we use this currently only for distance.
// For other scalar results area,length,perimeter it is commented on purpose.
// Reason is that for distance there is no other choice. distance of two
@@ -46,7 +51,7 @@ inline void throw_on_empty_input(Geometry const& geometry)
#if ! defined(BOOST_GEOMETRY_EMPTY_INPUT_NO_THROW)
if (geometry::is_empty(geometry))
{
- throw empty_input_exception();
+ BOOST_THROW_EXCEPTION(empty_input_exception());
}
#else
boost::ignore_unused(geometry);
diff --git a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
index a73364c333..a24f4d21e2 100644
--- a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
+++ b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
@@ -5,8 +5,10 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -15,8 +17,6 @@
// 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_WITHIN_POINT_IN_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP
@@ -35,8 +35,7 @@
#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/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/relate.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp>
@@ -46,6 +45,7 @@ namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within {
+
// TODO: is this needed?
inline int check_result_type(int result)
{
@@ -83,50 +83,11 @@ int point_in_range(Point const& point, Range const& range, Strategy const& strat
template <typename Geometry, typename Point, typename Range>
inline int point_in_range(Point const& point, Range const& range)
{
- typedef typename point_type<Point>::type point_type1;
- typedef typename point_type<Geometry>::type point_type2;
-
- typedef typename strategy::within::services::default_strategy
+ typedef typename strategy::point_in_geometry::services::default_strategy
<
- typename tag<Point>::type,
- typename tag<Geometry>::type,
- typename tag<Point>::type,
- typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,
- typename tag_cast
- <
- typename cs_tag<point_type1>::type, spherical_tag
- >::type,
- typename tag_cast
- <
- typename cs_tag<point_type2>::type, spherical_tag
- >::type,
- Point,
- Geometry
+ Point, Geometry
>::type strategy_type;
- typedef typename strategy::covered_by::services::default_strategy
- <
- typename tag<Point>::type,
- typename tag<Geometry>::type,
- typename tag<Point>::type,
- typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,
- typename tag_cast
- <
- typename cs_tag<point_type1>::type, spherical_tag
- >::type,
- typename tag_cast
- <
- typename cs_tag<point_type2>::type, spherical_tag
- >::type,
- Point,
- Geometry
- >::type strategy_type2;
-
- static const bool same_strategies = boost::is_same<strategy_type, strategy_type2>::value;
- BOOST_MPL_ASSERT_MSG((same_strategies),
- DEFAULT_WITHIN_AND_COVERED_BY_STRATEGIES_NOT_COMPATIBLE,
- (strategy_type, strategy_type2));
-
return point_in_range(point, range, strategy_type());
}
@@ -414,50 +375,11 @@ inline int point_in_geometry(Point const& point, Geometry const& geometry, Strat
template <typename Point, typename Geometry>
inline int point_in_geometry(Point const& point, Geometry const& geometry)
{
- typedef typename point_type<Point>::type point_type1;
- typedef typename point_type<Geometry>::type point_type2;
-
- typedef typename strategy::within::services::default_strategy
+ typedef typename strategy::point_in_geometry::services::default_strategy
<
- typename tag<Point>::type,
- typename tag<Geometry>::type,
- typename tag<Point>::type,
- typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,
- typename tag_cast
- <
- typename cs_tag<point_type1>::type, spherical_tag
- >::type,
- typename tag_cast
- <
- typename cs_tag<point_type2>::type, spherical_tag
- >::type,
- Point,
- Geometry
+ Point, Geometry
>::type strategy_type;
- typedef typename strategy::covered_by::services::default_strategy
- <
- typename tag<Point>::type,
- typename tag<Geometry>::type,
- typename tag<Point>::type,
- typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,
- typename tag_cast
- <
- typename cs_tag<point_type1>::type, spherical_tag
- >::type,
- typename tag_cast
- <
- typename cs_tag<point_type2>::type, spherical_tag
- >::type,
- Point,
- Geometry
- >::type strategy_type2;
-
- static const bool same_strategies = boost::is_same<strategy_type, strategy_type2>::value;
- BOOST_MPL_ASSERT_MSG((same_strategies),
- DEFAULT_WITHIN_AND_COVERED_BY_STRATEGIES_NOT_COMPATIBLE,
- (strategy_type, strategy_type2));
-
return point_in_geometry(point, geometry, strategy_type());
}
diff --git a/boost/geometry/algorithms/difference.hpp b/boost/geometry/algorithms/difference.hpp
index f7ca48cbe6..c11ceca243 100644
--- a/boost/geometry/algorithms/difference.hpp
+++ b/boost/geometry/algorithms/difference.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)
@@ -9,10 +14,16 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
-#include <algorithm>
+
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/util/range.hpp>
+
namespace boost { namespace geometry
{
@@ -49,10 +60,10 @@ template
typename Strategy
>
inline OutputIterator difference_insert(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- RobustPolicy const& robust_policy,
- OutputIterator out,
- Strategy const& strategy)
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ OutputIterator out,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
@@ -93,25 +104,18 @@ template
typename OutputIterator
>
inline OutputIterator difference_insert(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- RobustPolicy const& robust_policy,
- OutputIterator out)
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ OutputIterator out)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
- concepts::check<GeometryOut>();
-
- typedef intersection_strategies
+ typedef typename strategy::relate::services::default_strategy
<
- typename cs_tag<GeometryOut>::type,
Geometry1,
- Geometry2,
- typename geometry::point_type<GeometryOut>::type,
- RobustPolicy
- > strategy;
+ Geometry2
+ >::type strategy_type;
return difference_insert<GeometryOut>(geometry1, geometry2,
- robust_policy, out, strategy());
+ robust_policy, out, strategy_type());
}
@@ -119,6 +123,215 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
#endif // DOXYGEN_NO_DETAIL
+namespace resolve_strategy {
+
+struct difference
+{
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename Collection,
+ typename Strategy
+ >
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ detail::difference::difference_insert<geometry_out>(
+ geometry1, geometry2, robust_policy,
+ range::back_inserter(output_collection),
+ strategy);
+ }
+
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename Collection
+ >
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ Collection & output_collection,
+ default_strategy)
+ {
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ detail::difference::difference_insert<geometry_out>(
+ geometry1, geometry2, robust_policy,
+ range::back_inserter(output_collection));
+ }
+};
+
+} // resolve_strategy
+
+
+namespace resolve_variant
+{
+
+template <typename Geometry1, typename Geometry2>
+struct difference
+{
+ template <typename Collection, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ typedef typename geometry::rescale_overlay_policy_type
+ <
+ Geometry1,
+ Geometry2
+ >::type rescale_policy_type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry1,
+ geometry2);
+
+ resolve_strategy::difference::apply(geometry1, geometry2,
+ robust_policy,
+ output_collection,
+ strategy);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct difference<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Geometry2 const& m_geometry2;
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1>
+ void operator()(Geometry1 const& geometry1) const
+ {
+ difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
+ output_collection,
+ strategy),
+ geometry1);
+ }
+};
+
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct difference<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Geometry1 const& m_geometry1;
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Geometry1 const& geometry1,
+ Collection& output_collection,
+ Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry2>
+ void operator()(Geometry2 const& geometry2) const
+ {
+ difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(Geometry1 const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
+ output_collection,
+ strategy),
+ geometry2);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
+struct difference<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Collection& output_collection, Strategy const& strategy)
+ : m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1, typename Geometry2>
+ void operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
+ strategy),
+ geometry1, geometry2);
+ }
+};
+
+} // namespace resolve_variant
+
/*!
\brief_calc2{difference}
@@ -127,39 +340,63 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Collection \tparam_output_collection
+\tparam Strategy \tparam_strategy{Difference}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param output_collection the output collection
+\param strategy \param_strategy{difference}
+\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/difference.qbk]}
*/
template
<
typename Geometry1,
typename Geometry2,
- typename Collection
+ typename Collection,
+ typename Strategy
>
inline void difference(Geometry1 const& geometry1,
- Geometry2 const& geometry2, Collection& output_collection)
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
- typedef typename boost::range_value<Collection>::type geometry_out;
- concepts::check<geometry_out>();
-
- typedef typename geometry::rescale_overlay_policy_type
+ resolve_variant::difference
<
Geometry1,
Geometry2
- >::type rescale_policy_type;
+ >::apply(geometry1, geometry2, output_collection, strategy);
+}
- rescale_policy_type robust_policy
- = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
- detail::difference::difference_insert<geometry_out>(
- geometry1, geometry2, robust_policy,
- range::back_inserter(output_collection));
+/*!
+\brief_calc2{difference}
+\ingroup difference
+\details \details_calc2{difference, spatial set theoretic difference}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Collection \tparam_output_collection
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param output_collection the output collection
+
+\qbk{[include reference/algorithms/difference.qbk]}
+*/
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Collection
+>
+inline void difference(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection)
+{
+ resolve_variant::difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, output_collection, default_strategy());
}
diff --git a/boost/geometry/algorithms/dispatch/disjoint.hpp b/boost/geometry/algorithms/dispatch/disjoint.hpp
index 627bcff83c..78015f1a55 100644
--- a/boost/geometry/algorithms/dispatch/disjoint.hpp
+++ b/boost/geometry/algorithms/dispatch/disjoint.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
@@ -60,6 +60,29 @@ struct disjoint
: not_implemented<Geometry1, Geometry2>
{};
+
+// If reversal is needed, perform it
+template
+<
+ typename Geometry1, typename Geometry2,
+ std::size_t DimensionCount,
+ typename Tag1, typename Tag2
+>
+struct disjoint<Geometry1, Geometry2, DimensionCount, Tag1, Tag2, true>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
+ {
+ return disjoint
+ <
+ Geometry2, Geometry1,
+ DimensionCount,
+ Tag2, Tag1
+ >::apply(g2, g1, strategy);
+ }
+};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/equals.hpp b/boost/geometry/algorithms/equals.hpp
index d04d5c7f3a..1479ea66fa 100644
--- a/boost/geometry/algorithms/equals.hpp
+++ b/boost/geometry/algorithms/equals.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 2014, 2015, 2016.
-// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
+// 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
@@ -26,6 +26,7 @@
#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>
@@ -40,7 +41,6 @@
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
-#include <boost/geometry/algorithms/detail/not.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
// For trivial checks
@@ -70,25 +70,44 @@ 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>
- static inline bool apply(Box1 const& box1, Box2 const& box2)
+ 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);
+ 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>
- static inline bool apply(Box1 const& , Box2 const& )
+ template <typename Box1, typename Box2, typename Strategy>
+ static inline bool apply(Box1 const& , Box2 const& , Strategy const& )
{
return true;
}
@@ -97,8 +116,8 @@ struct box_box<DimensionCount, DimensionCount>
struct segment_segment
{
- template <typename Segment1, typename Segment2>
- static inline bool apply(Segment1 const& segment1, Segment2 const& segment2)
+ 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),
@@ -119,55 +138,75 @@ struct segment_segment
struct area_check
{
- template <typename Geometry1, typename Geometry2>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ 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),
- geometry::area(geometry2));
+ 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>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ 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),
- geometry::length(geometry2));
+ 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>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ 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))
+ if (! TrivialCheck::apply(geometry1, geometry2, strategy))
{
return false;
}
- typedef typename geometry::select_most_precise
- <
- typename select_coordinate_type
- <
- Geometry1, Geometry2
- >::type,
- double
- >::type calculation_type;
-
- typedef geometry::collected_vector
+ typedef typename collected_vector
<
- calculation_type,
- Geometry1
- > collected_vector;
+ Geometry1, Geometry2, Strategy
+ >::type collected_vector_type;
- std::vector<collected_vector> c1, c2;
+ std::vector<collected_vector_type> c1, c2;
geometry::collect_vectors(c1, geometry1);
geometry::collect_vectors(c2, geometry2);
@@ -195,6 +234,53 @@ struct equals_by_relate
>
{};
+// 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
@@ -226,7 +312,8 @@ template
struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
: equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
return equals
<
@@ -234,19 +321,30 @@ struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
Tag2, Tag1,
DimensionCount,
false
- >::apply(g2, g1);
+ >::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>
- : geometry::detail::not_
- <
- detail::disjoint::point_point<P1, P2, 0, DimensionCount>
- >
+ : 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>
@@ -256,19 +354,19 @@ struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
template <typename Ring1, typename Ring2, bool Reverse>
struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
- : detail::equals::equals_by_collection<detail::equals::area_check>
+ : 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<detail::equals::area_check>
+ : 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<detail::equals::area_check>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
@@ -290,7 +388,6 @@ struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reve
template <typename LineString1, typename LineString2, bool Reverse>
struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
- //: detail::equals::equals_by_collection<detail::equals::length_check>
: detail::equals::equals_by_relate<LineString1, LineString2>
{};
@@ -313,7 +410,7 @@ struct equals
2,
Reverse
>
- : detail::equals::equals_by_collection<detail::equals::area_check>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
@@ -325,7 +422,7 @@ struct equals
2,
Reverse
>
- : detail::equals::equals_by_collection<detail::equals::area_check>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename MultiPolygon, typename Ring, bool Reverse>
@@ -336,7 +433,7 @@ struct equals
2,
Reverse
>
- : detail::equals::equals_by_collection<detail::equals::area_check>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
@@ -344,80 +441,129 @@ struct equals
#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)
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
concepts::check_concepts_and_equal_dimensions
- <
- Geometry1 const,
- Geometry2 const
- >();
+ <
+ Geometry1 const,
+ Geometry2 const
+ >();
- return dispatch::equals<Geometry1, Geometry2>
- ::apply(geometry1, geometry2);
+ 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)
+ 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);
+ ::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
+ Geometry2 const& geometry2,
+ Strategy const& strategy
)
{
- return boost::apply_visitor(visitor(geometry2), geometry1);
+ 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)
+ 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);
+ ::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
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Strategy const& strategy
)
{
- return boost::apply_visitor(visitor(geometry1), geometry2);
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
@@ -430,24 +576,33 @@ struct equals<
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);
+ ::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
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Strategy const& strategy
)
{
- return boost::apply_visitor(visitor(), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
@@ -464,18 +619,48 @@ struct equals<
\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);
+ ::apply(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/intersects.hpp b/boost/geometry/algorithms/intersects.hpp
index 5349db76bb..12ae169f12 100644
--- a/boost/geometry/algorithms/intersects.hpp
+++ b/boost/geometry/algorithms/intersects.hpp
@@ -4,10 +4,11 @@
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
-// 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 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.
@@ -29,6 +30,8 @@
#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
{
@@ -52,6 +55,10 @@ 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
@@ -67,13 +74,14 @@ inline bool intersects(Geometry const& geometry)
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, robust_policy, turns, policy);
+ >::apply(geometry, strategy, robust_policy, turns, policy);
return policy.has_intersections;
}
@@ -83,6 +91,32 @@ inline bool intersects(Geometry const& geometry)
\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}
diff --git a/boost/geometry/algorithms/overlaps.hpp b/boost/geometry/algorithms/overlaps.hpp
index 32738c294c..bedf17599b 100644
--- a/boost/geometry/algorithms/overlaps.hpp
+++ b/boost/geometry/algorithms/overlaps.hpp
@@ -4,8 +4,8 @@
// 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.
-// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
+// 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
@@ -113,8 +113,8 @@ struct box_box_loop<DimensionCount, DimensionCount>
struct box_box
{
- template <typename Box1, typename Box2>
- static inline bool apply(Box1 const& b1, Box2 const& b2)
+ 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;
@@ -137,7 +137,6 @@ struct box_box
}} // namespace detail::overlaps
#endif // DOXYGEN_NO_DETAIL
-//struct not_implemented_for_this_geometry_type : public boost::false_type {};
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
@@ -175,6 +174,35 @@ struct overlaps<Box1, Box2, box_tag, box_tag>
\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}
@@ -187,11 +215,17 @@ 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);
+ >::apply(geometry1, geometry2, strategy_type());
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/sym_difference.hpp b/boost/geometry/algorithms/sym_difference.hpp
index 33f94c9321..725230cd5b 100644
--- a/boost/geometry/algorithms/sym_difference.hpp
+++ b/boost/geometry/algorithms/sym_difference.hpp
@@ -2,10 +2,11 @@
// Copyright (c) 2007-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
@@ -14,13 +15,21 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
+
#include <algorithm>
#include <iterator>
#include <vector>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/union.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
+#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
@@ -276,14 +285,10 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
concepts::check<Geometry2 const>();
concepts::check<GeometryOut>();
- typedef intersection_strategies
+ typedef typename strategy::intersection::services::default_strategy
<
- typename cs_tag<GeometryOut>::type,
- Geometry1,
- Geometry2,
- typename geometry::point_type<GeometryOut>::type,
- RobustPolicy
- > strategy_type;
+ typename cs_tag<GeometryOut>::type
+ >::type strategy_type;
return sym_difference_insert<GeometryOut>(geometry1, geometry2, robust_policy, out, strategy_type());
}
@@ -292,6 +297,216 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
#endif // DOXYGEN_NO_DETAIL
+namespace resolve_strategy {
+
+struct sym_difference
+{
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename Collection,
+ typename Strategy
+ >
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ detail::sym_difference::sym_difference_insert<geometry_out>(
+ geometry1, geometry2, robust_policy,
+ range::back_inserter(output_collection),
+ strategy);
+ }
+
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename Collection
+ >
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ Collection & output_collection,
+ default_strategy)
+ {
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ detail::sym_difference::sym_difference_insert<geometry_out>(
+ geometry1, geometry2, robust_policy,
+ range::back_inserter(output_collection));
+ }
+};
+
+} // resolve_strategy
+
+
+namespace resolve_variant
+{
+
+template <typename Geometry1, typename Geometry2>
+struct sym_difference
+{
+ template <typename Collection, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ typedef typename geometry::rescale_overlay_policy_type
+ <
+ Geometry1,
+ Geometry2
+ >::type rescale_policy_type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry1,
+ geometry2);
+
+ resolve_strategy::sym_difference::apply(geometry1, geometry2,
+ robust_policy,
+ output_collection,
+ strategy);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Geometry2 const& m_geometry2;
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1>
+ void operator()(Geometry1 const& geometry1) const
+ {
+ sym_difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
+ output_collection,
+ strategy),
+ geometry1);
+ }
+};
+
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct sym_difference<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Geometry1 const& m_geometry1;
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Geometry1 const& geometry1,
+ Collection& output_collection,
+ Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry2>
+ void operator()(Geometry2 const& geometry2) const
+ {
+ sym_difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(Geometry1 const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
+ output_collection,
+ strategy),
+ geometry2);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
+struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Collection& output_collection, Strategy const& strategy)
+ : m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1, typename Geometry2>
+ void operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ sym_difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
+ strategy),
+ geometry1, geometry2);
+ }
+};
+
+} // namespace resolve_variant
+
+
/*!
\brief \brief_calc2{symmetric difference}
\ingroup sym_difference
@@ -300,39 +515,64 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
\tparam Geometry2 \tparam_geometry
\tparam Collection output collection, either a multi-geometry,
or a std::vector<Geometry> / std::deque<Geometry> etc
+\tparam Strategy \tparam_strategy{Sym_difference}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param output_collection the output collection
+\param strategy \param_strategy{sym_difference}
+\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/sym_difference.qbk]}
*/
template
<
typename Geometry1,
typename Geometry2,
- typename Collection
+ typename Collection,
+ typename Strategy
>
inline void sym_difference(Geometry1 const& geometry1,
- Geometry2 const& geometry2, Collection& output_collection)
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
- typedef typename boost::range_value<Collection>::type geometry_out;
- concepts::check<geometry_out>();
-
- typedef typename geometry::rescale_overlay_policy_type
+ resolve_variant::sym_difference
<
Geometry1,
Geometry2
- >::type rescale_policy_type;
+ >::apply(geometry1, geometry2, output_collection, strategy);
+}
- rescale_policy_type robust_policy
- = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
- detail::sym_difference::sym_difference_insert<geometry_out>(
- geometry1, geometry2, robust_policy,
- range::back_inserter(output_collection));
+/*!
+\brief \brief_calc2{symmetric difference}
+\ingroup sym_difference
+\details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Collection output collection, either a multi-geometry,
+ or a std::vector<Geometry> / std::deque<Geometry> etc
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param output_collection the output collection
+
+\qbk{[include reference/algorithms/sym_difference.qbk]}
+*/
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Collection
+>
+inline void sym_difference(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection)
+{
+ resolve_variant::sym_difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, output_collection, default_strategy());
}
diff --git a/boost/geometry/algorithms/touches.hpp b/boost/geometry/algorithms/touches.hpp
index 6384cc2a88..49e104d258 100644
--- a/boost/geometry/algorithms/touches.hpp
+++ b/boost/geometry/algorithms/touches.hpp
@@ -5,8 +5,8 @@
// 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.
-// 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
@@ -104,8 +104,8 @@ struct box_box_loop<DimensionCount, DimensionCount>
struct box_box
{
- template <typename Box1, typename Box2>
- static inline bool apply(Box1 const& b1, Box2 const& b2)
+ 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
<
@@ -205,15 +205,17 @@ struct areal_interrupt_policy
}
};
-template<typename Geometry>
+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)
+ inline check_each_ring_for_within(Geometry const& g, PointInRingStrategy const& strategy)
: has_within(false)
, m_geometry(g)
+ , m_strategy(strategy)
{}
template <typename Range>
@@ -221,18 +223,31 @@ struct check_each_ring_for_within
{
typename geometry::point_type<Range>::type p;
geometry::point_on_border(p, range);
- if ( !has_within && geometry::within(p, m_geometry) )
+ if ( !has_within && geometry::within(p, m_geometry, m_strategy) )
{
has_within = true;
}
}
};
-template <typename FirstGeometry, typename SecondGeometry>
+template <typename FirstGeometry, typename SecondGeometry, typename IntersectionStrategy>
inline bool rings_containing(FirstGeometry const& geometry1,
- SecondGeometry const& geometry2)
+ SecondGeometry const& geometry2,
+ IntersectionStrategy const& strategy)
{
- check_each_ring_for_within<FirstGeometry> checker(geometry1);
+ // 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;
}
@@ -240,8 +255,10 @@ inline bool rings_containing(FirstGeometry const& geometry1,
template <typename Geometry1, typename Geometry2>
struct areal_areal
{
- static inline
- bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ 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;
@@ -259,11 +276,11 @@ struct areal_areal
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, robust_policy, turns, policy);
+ >(geometry1, geometry2, strategy, robust_policy, turns, policy);
return policy.result()
- && ! geometry::detail::touches::rings_containing(geometry1, geometry2)
- && ! geometry::detail::touches::rings_containing(geometry2, geometry1);
+ && ! geometry::detail::touches::rings_containing(geometry1, geometry2, strategy)
+ && ! geometry::detail::touches::rings_containing(geometry2, geometry1, strategy);
}
};
@@ -271,10 +288,10 @@ struct areal_areal
struct use_point_in_geometry
{
- template <typename Point, typename Geometry>
- static inline bool apply(Point const& point, Geometry const& 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) == 0;
+ return detail::within::point_in_geometry(point, geometry, strategy) == 0;
}
};
@@ -288,7 +305,8 @@ namespace dispatch {
template
<
- typename Geometry1, typename Geometry2,
+ 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,
@@ -309,18 +327,30 @@ template
struct touches<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, true>
: touches<Geometry2, Geometry1, Tag2, Tag1, CastedTag2, CastedTag1, false>
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
- return touches<Geometry2, Geometry1>::apply(g2, g1);
+ return touches<Geometry2, Geometry1>::apply(g2, g1, strategy);
}
};
// P/P
-template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>
-struct touches<Geometry1, Geometry2, Tag1, Tag2, pointlike_tag, pointlike_tag, false>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct touches<Geometry1, Geometry2, point_tag, Tag2, pointlike_tag, pointlike_tag, false>
{
- static inline bool apply(Geometry1 const& , Geometry2 const& )
+ 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;
}
@@ -403,66 +433,115 @@ struct touches<Areal1, Areal2, ring_tag, ring_tag, areal_tag, areal_tag, false>
#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
{
- static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename Strategy>
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- return dispatch::touches<Geometry1, Geometry2>
- ::apply(geometry1, geometry2);
+ 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): m_geometry2(geometry2) {}
+ 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);
+ return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
}
};
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2)
+ 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(geometry2), geometry1);
+ 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): m_geometry1(geometry1) {}
+ 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);
+ return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
}
};
- static inline bool
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
+ 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(geometry1), geometry2);
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
@@ -471,21 +550,29 @@ template <BOOST_VARIANT_ENUM_PARAMS(typename T1),
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);
+ return touches<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
}
};
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
+ 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(), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
@@ -496,6 +583,10 @@ struct self_touches
{
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
@@ -511,11 +602,12 @@ struct self_touches
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, robust_policy, turns, policy);
+ >::apply(geometry, strategy, robust_policy, turns, policy);
return policy.result();
}
@@ -578,7 +670,35 @@ inline bool touches(Geometry const& geometry)
template <typename Geometry1, typename Geometry2>
inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::touches<Geometry1, Geometry2>::apply(geometry1, 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);
}
diff --git a/boost/geometry/algorithms/union.hpp b/boost/geometry/algorithms/union.hpp
index f0e55ec981..d3a2daf66e 100644
--- a/boost/geometry/algorithms/union.hpp
+++ b/boost/geometry/algorithms/union.hpp
@@ -2,10 +2,11 @@
// 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
@@ -24,6 +25,8 @@
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
@@ -214,14 +217,10 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
Geometry2
>::type rescale_policy_type;
- typedef intersection_strategies
+ typename strategy::intersection::services::default_strategy
<
- typename cs_tag<GeometryOut>::type,
- Geometry1,
- Geometry2,
- typename geometry::point_type<GeometryOut>::type,
- rescale_policy_type
- > strategy;
+ typename cs_tag<GeometryOut>::type
+ >::type strategy;
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
@@ -229,7 +228,7 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
return dispatch::union_insert
<
Geometry1, Geometry2, GeometryOut
- >::apply(geometry1, geometry2, robust_policy, out, strategy());
+ >::apply(geometry1, geometry2, robust_policy, out, strategy);
}
@@ -237,6 +236,228 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
#endif // DOXYGEN_NO_DETAIL
+namespace resolve_strategy {
+
+struct union_
+{
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename Collection,
+ typename Strategy
+ >
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ dispatch::union_insert
+ <
+ Geometry1, Geometry2, geometry_out
+ >::apply(geometry1, geometry2, robust_policy,
+ range::back_inserter(output_collection),
+ strategy);
+ }
+
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename Collection
+ >
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ Collection & output_collection,
+ default_strategy)
+ {
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ typedef typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<geometry_out>::type
+ >::type strategy_type;
+
+ dispatch::union_insert
+ <
+ Geometry1, Geometry2, geometry_out
+ >::apply(geometry1, geometry2, robust_policy,
+ range::back_inserter(output_collection),
+ strategy_type());
+ }
+};
+
+} // resolve_strategy
+
+
+namespace resolve_variant
+{
+
+template <typename Geometry1, typename Geometry2>
+struct union_
+{
+ template <typename Collection, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+ concepts::check<typename boost::range_value<Collection>::type>();
+
+ typedef typename geometry::rescale_overlay_policy_type
+ <
+ Geometry1,
+ Geometry2
+ >::type rescale_policy_type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry1,
+ geometry2);
+
+ resolve_strategy::union_::apply(geometry1, geometry2,
+ robust_policy,
+ output_collection,
+ strategy);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Geometry2 const& m_geometry2;
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1>
+ void operator()(Geometry1 const& geometry1) const
+ {
+ union_
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
+ output_collection,
+ strategy),
+ geometry1);
+ }
+};
+
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct union_<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Geometry1 const& m_geometry1;
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Geometry1 const& geometry1,
+ Collection& output_collection,
+ Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry2>
+ void operator()(Geometry2 const& geometry2) const
+ {
+ union_
+ <
+ Geometry1,
+ Geometry2
+ >::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(Geometry1 const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
+ output_collection,
+ strategy),
+ geometry2);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
+struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Collection& output_collection, Strategy const& strategy)
+ : m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1, typename Geometry2>
+ void operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ union_
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
+ strategy),
+ geometry1, geometry2);
+ }
+};
+
+} // namespace resolve_variant
/*!
@@ -247,31 +468,66 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
\tparam Geometry2 \tparam_geometry
\tparam Collection output collection, either a multi-geometry,
or a std::vector<Geometry> / std::deque<Geometry> etc
+\tparam Strategy \tparam_strategy{Union_}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param output_collection the output collection
+\param strategy \param_strategy{union_}
\note Called union_ because union is a reserved word.
+\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/union.qbk]}
*/
template
<
typename Geometry1,
typename Geometry2,
- typename Collection
+ typename Collection,
+ typename Strategy
>
inline void union_(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Collection& output_collection)
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
+ resolve_variant::union_
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, output_collection, strategy);
+}
- typedef typename boost::range_value<Collection>::type geometry_out;
- concepts::check<geometry_out>();
- detail::union_::union_insert<geometry_out>(geometry1, geometry2,
- range::back_inserter(output_collection));
+/*!
+\brief Combines two geometries which each other
+\ingroup union
+\details \details_calc2{union, spatial set theoretic union}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Collection output collection, either a multi-geometry,
+ or a std::vector<Geometry> / std::deque<Geometry> etc
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param output_collection the output collection
+\note Called union_ because union is a reserved word.
+
+\qbk{[include reference/algorithms/union.qbk]}
+*/
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Collection
+>
+inline void union_(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection)
+{
+ resolve_variant::union_
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, output_collection, default_strategy());
}
diff --git a/boost/geometry/algorithms/within.hpp b/boost/geometry/algorithms/within.hpp
index a1e6a58f8d..ba170dd27b 100644
--- a/boost/geometry/algorithms/within.hpp
+++ b/boost/geometry/algorithms/within.hpp
@@ -4,8 +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 2013, 2014.
-// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.
+// 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.
@@ -14,8 +16,6 @@
// 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_WITHIN_HPP
#define BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
@@ -52,6 +52,7 @@
#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>
@@ -75,9 +76,13 @@ struct use_point_in_geometry
struct use_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/)
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
- return Strategy::apply(geometry1, geometry2);
+ typedef typename detail::de9im::static_mask_within_type
+ <
+ Geometry1, Geometry2
+ >::type within_mask;
+ return geometry::relate(geometry1, geometry2, within_mask(), strategy);
}
};
@@ -300,23 +305,8 @@ struct within
Geometry2 const& geometry2,
default_strategy)
{
- typedef typename point_type<Geometry1>::type point_type1;
- typedef typename point_type<Geometry2>::type point_type2;
-
typedef typename strategy::within::services::default_strategy
<
- typename tag<Geometry1>::type,
- typename tag<Geometry2>::type,
- typename tag<Geometry1>::type,
- typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
- typename tag_cast
- <
- typename cs_tag<point_type1>::type, spherical_tag
- >::type,
- typename tag_cast
- <
- typename cs_tag<point_type2>::type, spherical_tag
- >::type,
Geometry1,
Geometry2
>::type strategy_type;
@@ -517,8 +507,9 @@ inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
}
*/
template<typename Geometry1, typename Geometry2, typename Strategy>
-inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2,
- Strategy const& strategy)
+inline bool within(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
return resolve_variant::within
<
diff --git a/boost/geometry/arithmetic/normalize.hpp b/boost/geometry/arithmetic/normalize.hpp
new file mode 100644
index 0000000000..7dfdbd2b03
--- /dev/null
+++ b/boost/geometry/arithmetic/normalize.hpp
@@ -0,0 +1,71 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016, 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_ARITHMETIC_NORMALIZE_HPP
+#define BOOST_GEOMETRY_ARITHMETIC_NORMALIZE_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/arithmetic/dot_product.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Point>
+inline typename coordinate_type<Point>::type vec_length_sqr(Point const& pt)
+{
+ return dot_product(pt, pt);
+}
+
+template <typename Point>
+inline typename coordinate_type<Point>::type vec_length(Point const& pt)
+{
+ // NOTE: hypot() could be used instead of sqrt()
+ return math::sqrt(dot_product(pt, pt));
+}
+
+template <typename Point>
+inline bool vec_normalize(Point & pt, typename coordinate_type<Point>::type & len)
+{
+ typedef typename coordinate_type<Point>::type coord_t;
+
+ coord_t const c0 = 0;
+ len = vec_length(pt);
+
+ if (math::equals(len, c0))
+ {
+ return false;
+ }
+
+ divide_value(pt, len);
+ return true;
+}
+
+template <typename Point>
+inline bool vec_normalize(Point & pt)
+{
+ typedef typename coordinate_type<Point>::type coord_t;
+ coord_t len;
+ return vec_normalize(pt, len);
+}
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ARITHMETIC_NORMALIZE_HPP
diff --git a/boost/geometry/core/srs.hpp b/boost/geometry/core/srs.hpp
index bf1b4e28a5..5c78b9f1fc 100644
--- a/boost/geometry/core/srs.hpp
+++ b/boost/geometry/core/srs.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// 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, 2016, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -51,7 +51,7 @@ public:
spheroid()
: m_a(RadiusType(6378137.0))
- , m_b(RadiusType(6356752.314245))
+ , m_b(RadiusType(6356752.3142451793))
{}
template <std::size_t I>
@@ -126,8 +126,9 @@ public:
explicit sphere(RadiusType const& r)
: m_r(r)
{}
+
sphere()
- : m_r(RadiusType((2.0 * 6378137.0 + 6356752.314245) / 3.0))
+ : m_r(RadiusType((2.0 * 6378137.0 + 6356752.3142451793) / 3.0))
{}
template <std::size_t I>
diff --git a/boost/geometry/formulas/andoyer_inverse.hpp b/boost/geometry/formulas/andoyer_inverse.hpp
index 57b5ab5384..902fd7d8f6 100644
--- a/boost/geometry/formulas/andoyer_inverse.hpp
+++ b/boost/geometry/formulas/andoyer_inverse.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2015-2016 Oracle and/or its affiliates.
+// Copyright (c) 2015-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -20,9 +20,8 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/result_inverse.hpp>
@@ -75,7 +74,7 @@ public:
CT const c0 = CT(0);
CT const c1 = CT(1);
CT const pi = math::pi<CT>();
- CT const f = detail::flattening<CT>(spheroid);
+ CT const f = formula::flattening<CT>(spheroid);
CT const dlon = lon2 - lon1;
CT const sin_dlon = sin(dlon);
@@ -97,7 +96,7 @@ public:
CT const d = acos(cos_d); // [0, pi]
CT const sin_d = sin(d); // [-1, 1]
-
+
if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )
{
CT const K = math::sqr(sin_lat1-sin_lat2);
@@ -138,7 +137,14 @@ public:
CT A = c0;
CT U = c0;
- if ( ! math::equals(cos_lat2, c0) )
+ if (math::equals(cos_lat2, c0))
+ {
+ if (sin_lat2 < c0)
+ {
+ A = pi;
+ }
+ }
+ else
{
CT const tan_lat2 = sin_lat2/cos_lat2;
CT const M = cos_lat1*tan_lat2-sin_lat1*cos_dlon;
@@ -149,7 +155,14 @@ public:
CT B = c0;
CT V = c0;
- if ( ! math::equals(cos_lat1, c0) )
+ if (math::equals(cos_lat1, c0))
+ {
+ if (sin_lat1 < c0)
+ {
+ B = pi;
+ }
+ }
+ else
{
CT const tan_lat1 = sin_lat1/cos_lat1;
CT const N = cos_lat2*tan_lat1-sin_lat2*cos_dlon;
diff --git a/boost/geometry/formulas/area_formulas.hpp b/boost/geometry/formulas/area_formulas.hpp
new file mode 100644
index 0000000000..6a0b525e25
--- /dev/null
+++ b/boost/geometry/formulas/area_formulas.hpp
@@ -0,0 +1,578 @@
+// Boost.Geometry
+
+// Copyright (c) 2015-2016 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, 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_AREA_FORMULAS_HPP
+#define BOOST_GEOMETRY_FORMULAS_AREA_FORMULAS_HPP
+
+#include <boost/geometry/formulas/flattening.hpp>
+#include <boost/math/special_functions/hypot.hpp>
+
+namespace boost { namespace geometry { namespace formula
+{
+
+/*!
+\brief Formulas for computing spherical and ellipsoidal polygon area.
+ The current class computes the area of the trapezoid defined by a segment
+ the two meridians passing by the endpoints and the equator.
+\author See
+- Danielsen JS, The area under the geodesic. Surv Rev 30(232):
+61–66, 1989
+- Charles F.F Karney, Algorithms for geodesics, 2011
+https://arxiv.org/pdf/1109.4448.pdf
+*/
+
+template <
+ typename CT,
+ std::size_t SeriesOrder = 2,
+ bool ExpandEpsN = true
+>
+class area_formulas
+{
+
+public:
+
+ //TODO: move the following to a more general space to be used by other
+ // classes as well
+ /*
+ Evaluate the polynomial in x using Horner's method.
+ */
+ template <typename NT, typename IteratorType>
+ static inline NT horner_evaluate(NT x,
+ IteratorType begin,
+ IteratorType end)
+ {
+ NT result(0);
+ IteratorType it = end;
+ do
+ {
+ result = result * x + *--it;
+ }
+ while (it != begin);
+ return result;
+ }
+
+ /*
+ Clenshaw algorithm for summing trigonometric series
+ https://en.wikipedia.org/wiki/Clenshaw_algorithm
+ */
+ template <typename NT, typename IteratorType>
+ static inline NT clenshaw_sum(NT cosx,
+ IteratorType begin,
+ IteratorType end)
+ {
+ IteratorType it = end;
+ bool odd = true;
+ CT b_k, b_k1(0), b_k2(0);
+ do
+ {
+ CT c_k = odd ? *--it : NT(0);
+ b_k = c_k + NT(2) * cosx * b_k1 - b_k2;
+ b_k2 = b_k1;
+ b_k1 = b_k;
+ odd = !odd;
+ }
+ while (it != begin);
+
+ return *begin + b_k1 * cosx - b_k2;
+ }
+
+ template<typename T>
+ static inline void normalize(T& x, T& y)
+ {
+ T h = boost::math::hypot(x, y);
+ x /= h;
+ y /= h;
+ }
+
+ /*
+ Generate and evaluate the series expansion of the following integral
+
+ I4 = -integrate( (t(ep2) - t(k2*sin(sigma1)^2)) / (ep2 - k2*sin(sigma1)^2)
+ * sin(sigma1)/2, sigma1, pi/2, sigma )
+ where
+
+ t(x) = sqrt(1+1/x)*asinh(sqrt(x)) + x
+
+ valid for ep2 and k2 small. We substitute k2 = 4 * eps / (1 - eps)^2
+ and ep2 = 4 * n / (1 - n)^2 and expand in eps and n.
+
+ The resulting sum of the series is of the form
+
+ sum(C4[l] * cos((2*l+1)*sigma), l, 0, maxpow-1) )
+
+ The above expansion is performed in Computer Algebra System Maxima.
+ The C++ code (that yields the function evaluate_coeffs_n below) is generated
+ by the following Maxima script and is based on script:
+ http://geographiclib.sourceforge.net/html/geod.mac
+
+ // Maxima script begin
+ taylordepth:5$
+ ataylor(expr,var,ord):=expand(ratdisrep(taylor(expr,var,0,ord)))$
+ jtaylor(expr,var1,var2,ord):=block([zz],expand(subst([zz=1],
+ ratdisrep(taylor(subst([var1=zz*var1,var2=zz*var2],expr),zz,0,ord)))))$
+
+ compute(maxpow):=block([int,t,intexp,area, x,ep2,k2],
+ maxpow:maxpow-1,
+ t : sqrt(1+1/x) * asinh(sqrt(x)) + x,
+ int:-(tf(ep2) - tf(k2*sin(sigma)^2)) / (ep2 - k2*sin(sigma)^2)
+ * sin(sigma)/2,
+ int:subst([tf(ep2)=subst([x=ep2],t),
+ tf(k2*sin(sigma)^2)=subst([x=k2*sin(sigma)^2],t)],
+ int),
+ int:subst([abs(sin(sigma))=sin(sigma)],int),
+ int:subst([k2=4*eps/(1-eps)^2,ep2=4*n/(1-n)^2],int),
+ intexp:jtaylor(int,n,eps,maxpow),
+ area:trigreduce(integrate(intexp,sigma)),
+ area:expand(area-subst(sigma=%pi/2,area)),
+ for i:0 thru maxpow do C4[i]:coeff(area,cos((2*i+1)*sigma)),
+ if expand(area-sum(C4[i]*cos((2*i+1)*sigma),i,0,maxpow)) # 0
+ then error("left over terms in I4"),
+ 'done)$
+
+ printcode(maxpow):=
+ block([tab2:" ",tab3:" "],
+ print(" switch (SeriesOrder) {"),
+ for nn:1 thru maxpow do block([c],
+ print(concat(tab2,"case ",string(nn-1),":")),
+ c:0,
+ for m:0 thru nn-1 do block(
+ [q:jtaylor(subst([n=n],C4[m]),n,eps,nn-1),
+ linel:1200],
+ for j:m thru nn-1 do (
+ print(concat(tab3,"coeffs_n[",c,"] = ",
+ string(horner(coeff(q,eps,j))),";")),
+ c:c+1)
+ ),
+ print(concat(tab3,"break;"))),
+ print(" }"),
+ 'done)$
+
+ maxpow:6$
+ compute(maxpow)$
+ printcode(maxpow)$
+ // Maxima script end
+
+ In the resulting code we should replace each number x by CT(x)
+ e.g. using the following scirpt:
+ sed -e 's/[0-9]\+/CT(&)/g; s/\[CT(/\[/g; s/)\]/\]/g;
+ s/case\sCT(/case /g; s/):/:/g'
+ */
+
+ static inline void evaluate_coeffs_n(CT n, CT coeffs_n[])
+ {
+
+ switch (SeriesOrder) {
+ case 0:
+ coeffs_n[0] = CT(2)/CT(3);
+ break;
+ case 1:
+ coeffs_n[0] = (CT(10)-CT(4)*n)/CT(15);
+ coeffs_n[1] = -CT(1)/CT(5);
+ coeffs_n[2] = CT(1)/CT(45);
+ break;
+ case 2:
+ coeffs_n[0] = (n*(CT(8)*n-CT(28))+CT(70))/CT(105);
+ coeffs_n[1] = (CT(16)*n-CT(7))/CT(35);
+ coeffs_n[2] = -CT(2)/CT(105);
+ coeffs_n[3] = (CT(7)-CT(16)*n)/CT(315);
+ coeffs_n[4] = -CT(2)/CT(105);
+ coeffs_n[5] = CT(4)/CT(525);
+ break;
+ case 3:
+ coeffs_n[0] = (n*(n*(CT(4)*n+CT(24))-CT(84))+CT(210))/CT(315);
+ coeffs_n[1] = ((CT(48)-CT(32)*n)*n-CT(21))/CT(105);
+ coeffs_n[2] = (-CT(32)*n-CT(6))/CT(315);
+ coeffs_n[3] = CT(11)/CT(315);
+ coeffs_n[4] = (n*(CT(32)*n-CT(48))+CT(21))/CT(945);
+ coeffs_n[5] = (CT(64)*n-CT(18))/CT(945);
+ coeffs_n[6] = -CT(1)/CT(105);
+ coeffs_n[7] = (CT(12)-CT(32)*n)/CT(1575);
+ coeffs_n[8] = -CT(8)/CT(1575);
+ coeffs_n[9] = CT(8)/CT(2205);
+ break;
+ case 4:
+ coeffs_n[0] = (n*(n*(n*(CT(16)*n+CT(44))+CT(264))-CT(924))+CT(2310))/CT(3465);
+ coeffs_n[1] = (n*(n*(CT(48)*n-CT(352))+CT(528))-CT(231))/CT(1155);
+ coeffs_n[2] = (n*(CT(1088)*n-CT(352))-CT(66))/CT(3465);
+ coeffs_n[3] = (CT(121)-CT(368)*n)/CT(3465);
+ coeffs_n[4] = CT(4)/CT(1155);
+ coeffs_n[5] = (n*((CT(352)-CT(48)*n)*n-CT(528))+CT(231))/CT(10395);
+ coeffs_n[6] = ((CT(704)-CT(896)*n)*n-CT(198))/CT(10395);
+ coeffs_n[7] = (CT(80)*n-CT(99))/CT(10395);
+ coeffs_n[8] = CT(4)/CT(1155);
+ coeffs_n[9] = (n*(CT(320)*n-CT(352))+CT(132))/CT(17325);
+ coeffs_n[10] = (CT(384)*n-CT(88))/CT(17325);
+ coeffs_n[11] = -CT(8)/CT(1925);
+ coeffs_n[12] = (CT(88)-CT(256)*n)/CT(24255);
+ coeffs_n[13] = -CT(16)/CT(8085);
+ coeffs_n[14] = CT(64)/CT(31185);
+ break;
+ case 5:
+ coeffs_n[0] = (n*(n*(n*(n*(CT(100)*n+CT(208))+CT(572))+CT(3432))-CT(12012))+CT(30030))
+ /CT(45045);
+ coeffs_n[1] = (n*(n*(n*(CT(64)*n+CT(624))-CT(4576))+CT(6864))-CT(3003))/CT(15015);
+ coeffs_n[2] = (n*((CT(14144)-CT(10656)*n)*n-CT(4576))-CT(858))/CT(45045);
+ coeffs_n[3] = ((-CT(224)*n-CT(4784))*n+CT(1573))/CT(45045);
+ coeffs_n[4] = (CT(1088)*n+CT(156))/CT(45045);
+ coeffs_n[5] = CT(97)/CT(15015);
+ coeffs_n[6] = (n*(n*((-CT(64)*n-CT(624))*n+CT(4576))-CT(6864))+CT(3003))/CT(135135);
+ coeffs_n[7] = (n*(n*(CT(5952)*n-CT(11648))+CT(9152))-CT(2574))/CT(135135);
+ coeffs_n[8] = (n*(CT(5792)*n+CT(1040))-CT(1287))/CT(135135);
+ coeffs_n[9] = (CT(468)-CT(2944)*n)/CT(135135);
+ coeffs_n[10] = CT(1)/CT(9009);
+ coeffs_n[11] = (n*((CT(4160)-CT(1440)*n)*n-CT(4576))+CT(1716))/CT(225225);
+ coeffs_n[12] = ((CT(4992)-CT(8448)*n)*n-CT(1144))/CT(225225);
+ coeffs_n[13] = (CT(1856)*n-CT(936))/CT(225225);
+ coeffs_n[14] = CT(8)/CT(10725);
+ coeffs_n[15] = (n*(CT(3584)*n-CT(3328))+CT(1144))/CT(315315);
+ coeffs_n[16] = (CT(1024)*n-CT(208))/CT(105105);
+ coeffs_n[17] = -CT(136)/CT(63063);
+ coeffs_n[18] = (CT(832)-CT(2560)*n)/CT(405405);
+ coeffs_n[19] = -CT(128)/CT(135135);
+ coeffs_n[20] = CT(128)/CT(99099);
+ break;
+ }
+ }
+
+ /*
+ Expand in k2 and ep2.
+ */
+ static inline void evaluate_coeffs_ep(CT ep, CT coeffs_n[])
+ {
+ switch (SeriesOrder) {
+ case 0:
+ coeffs_n[0] = CT(2)/CT(3);
+ break;
+ case 1:
+ coeffs_n[0] = (CT(10)-ep)/CT(15);
+ coeffs_n[1] = -CT(1)/CT(20);
+ coeffs_n[2] = CT(1)/CT(180);
+ break;
+ case 2:
+ coeffs_n[0] = (ep*(CT(4)*ep-CT(7))+CT(70))/CT(105);
+ coeffs_n[1] = (CT(4)*ep-CT(7))/CT(140);
+ coeffs_n[2] = CT(1)/CT(42);
+ coeffs_n[3] = (CT(7)-CT(4)*ep)/CT(1260);
+ coeffs_n[4] = -CT(1)/CT(252);
+ coeffs_n[5] = CT(1)/CT(2100);
+ break;
+ case 3:
+ coeffs_n[0] = (ep*((CT(12)-CT(8)*ep)*ep-CT(21))+CT(210))/CT(315);
+ coeffs_n[1] = ((CT(12)-CT(8)*ep)*ep-CT(21))/CT(420);
+ coeffs_n[2] = (CT(3)-CT(2)*ep)/CT(126);
+ coeffs_n[3] = -CT(1)/CT(72);
+ coeffs_n[4] = (ep*(CT(8)*ep-CT(12))+CT(21))/CT(3780);
+ coeffs_n[5] = (CT(2)*ep-CT(3))/CT(756);
+ coeffs_n[6] = CT(1)/CT(360);
+ coeffs_n[7] = (CT(3)-CT(2)*ep)/CT(6300);
+ coeffs_n[8] = -CT(1)/CT(1800);
+ coeffs_n[9] = CT(1)/CT(17640);
+ break;
+ case 4:
+ coeffs_n[0] = (ep*(ep*(ep*(CT(64)*ep-CT(88))+CT(132))-CT(231))+CT(2310))/CT(3465);
+ coeffs_n[1] = (ep*(ep*(CT(64)*ep-CT(88))+CT(132))-CT(231))/CT(4620);
+ coeffs_n[2] = (ep*(CT(16)*ep-CT(22))+CT(33))/CT(1386);
+ coeffs_n[3] = (CT(8)*ep-CT(11))/CT(792);
+ coeffs_n[4] = CT(1)/CT(110);
+ coeffs_n[5] = (ep*((CT(88)-CT(64)*ep)*ep-CT(132))+CT(231))/CT(41580);
+ coeffs_n[6] = ((CT(22)-CT(16)*ep)*ep-CT(33))/CT(8316);
+ coeffs_n[7] = (CT(11)-CT(8)*ep)/CT(3960);
+ coeffs_n[8] = -CT(1)/CT(495);
+ coeffs_n[9] = (ep*(CT(16)*ep-CT(22))+CT(33))/CT(69300);
+ coeffs_n[10] = (CT(8)*ep-CT(11))/CT(19800);
+ coeffs_n[11] = CT(1)/CT(1925);
+ coeffs_n[12] = (CT(11)-CT(8)*ep)/CT(194040);
+ coeffs_n[13] = -CT(1)/CT(10780);
+ coeffs_n[14] = CT(1)/CT(124740);
+ break;
+ case 5:
+ coeffs_n[0] = (ep*(ep*(ep*((CT(832)-CT(640)*ep)*ep-CT(1144))+CT(1716))-CT(3003))+CT(30030))/CT(45045);
+ coeffs_n[1] = (ep*(ep*((CT(832)-CT(640)*ep)*ep-CT(1144))+CT(1716))-CT(3003))/CT(60060);
+ coeffs_n[2] = (ep*((CT(208)-CT(160)*ep)*ep-CT(286))+CT(429))/CT(18018);
+ coeffs_n[3] = ((CT(104)-CT(80)*ep)*ep-CT(143))/CT(10296);
+ coeffs_n[4] = (CT(13)-CT(10)*ep)/CT(1430);
+ coeffs_n[5] = -CT(1)/CT(156);
+ coeffs_n[6] = (ep*(ep*(ep*(CT(640)*ep-CT(832))+CT(1144))-CT(1716))+CT(3003))/CT(540540);
+ coeffs_n[7] = (ep*(ep*(CT(160)*ep-CT(208))+CT(286))-CT(429))/CT(108108);
+ coeffs_n[8] = (ep*(CT(80)*ep-CT(104))+CT(143))/CT(51480);
+ coeffs_n[9] = (CT(10)*ep-CT(13))/CT(6435);
+ coeffs_n[10] = CT(5)/CT(3276);
+ coeffs_n[11] = (ep*((CT(208)-CT(160)*ep)*ep-CT(286))+CT(429))/CT(900900);
+ coeffs_n[12] = ((CT(104)-CT(80)*ep)*ep-CT(143))/CT(257400);
+ coeffs_n[13] = (CT(13)-CT(10)*ep)/CT(25025);
+ coeffs_n[14] = -CT(1)/CT(2184);
+ coeffs_n[15] = (ep*(CT(80)*ep-CT(104))+CT(143))/CT(2522520);
+ coeffs_n[16] = (CT(10)*ep-CT(13))/CT(140140);
+ coeffs_n[17] = CT(5)/CT(45864);
+ coeffs_n[18] = (CT(13)-CT(10)*ep)/CT(1621620);
+ coeffs_n[19] = -CT(1)/CT(58968);
+ coeffs_n[20] = CT(1)/CT(792792);
+ break;
+ }
+ }
+
+ /*
+ Given the set of coefficients coeffs1[] evaluate on var2 and return
+ the set of coefficients coeffs2[]
+ */
+ static inline void evaluate_coeffs_var2(CT var2,
+ CT coeffs1[],
+ CT coeffs2[]){
+ std::size_t begin(0), end(0);
+ for(std::size_t i = 0; i <= SeriesOrder; i++){
+ end = begin + SeriesOrder + 1 - i;
+ coeffs2[i] = ((i==0) ? CT(1) : pow(var2,int(i)))
+ * horner_evaluate(var2, coeffs1 + begin, coeffs1 + end);
+ begin = end;
+ }
+ }
+
+ /*
+ Compute the spherical excess of a geodesic (or shperical) segment
+ */
+ template <
+ bool LongSegment,
+ typename PointOfSegment
+ >
+ static inline CT spherical(PointOfSegment const& p1,
+ PointOfSegment const& p2)
+ {
+ CT excess;
+
+ if(LongSegment) // not for segments parallel to equator
+ {
+ CT cbet1 = cos(geometry::get_as_radian<1>(p1));
+ CT sbet1 = sin(geometry::get_as_radian<1>(p1));
+ CT cbet2 = cos(geometry::get_as_radian<1>(p2));
+ CT sbet2 = sin(geometry::get_as_radian<1>(p2));
+
+ CT omg12 = geometry::get_as_radian<0>(p1)
+ - geometry::get_as_radian<0>(p2);
+ CT comg12 = cos(omg12);
+ CT somg12 = sin(omg12);
+
+ CT alp1 = atan2(cbet1 * sbet2
+ - sbet1 * cbet2 * comg12,
+ cbet2 * somg12);
+
+ CT alp2 = atan2(cbet1 * sbet2 * comg12
+ - sbet1 * cbet2,
+ cbet1 * somg12);
+
+ excess = alp2 - alp1;
+
+ } else {
+
+ // Trapezoidal formula
+
+ CT tan_lat1 =
+ tan(geometry::get_as_radian<1>(p1) / 2.0);
+ CT tan_lat2 =
+ tan(geometry::get_as_radian<1>(p2) / 2.0);
+
+ excess = CT(2.0)
+ * atan(((tan_lat1 + tan_lat2) / (CT(1) + tan_lat1 * tan_lat2))
+ * tan((geometry::get_as_radian<0>(p2)
+ - geometry::get_as_radian<0>(p1)) / 2));
+ }
+
+ return excess;
+ }
+
+ struct return_type_ellipsoidal
+ {
+ return_type_ellipsoidal()
+ : spherical_term(0),
+ ellipsoidal_term(0)
+ {}
+
+ CT spherical_term;
+ CT ellipsoidal_term;
+ };
+
+ /*
+ Compute the ellipsoidal correction of a geodesic (or shperical) segment
+ */
+ template <
+ template <typename, bool, bool, bool, bool, bool> class Inverse,
+ //typename AzimuthStrategy,
+ typename PointOfSegment,
+ typename SpheroidConst
+ >
+ static inline return_type_ellipsoidal ellipsoidal(PointOfSegment const& p1,
+ PointOfSegment const& p2,
+ SpheroidConst spheroid_const)
+ {
+ return_type_ellipsoidal result;
+
+ // Azimuth Approximation
+
+ typedef Inverse<CT, false, true, true, false, false> inverse_type;
+ typedef typename inverse_type::result_type inverse_result;
+
+ inverse_result i_res = inverse_type::apply(get_as_radian<0>(p1),
+ get_as_radian<1>(p1),
+ get_as_radian<0>(p2),
+ get_as_radian<1>(p2),
+ spheroid_const.m_spheroid);
+
+ CT alp1 = i_res.azimuth;
+ CT alp2 = i_res.reverse_azimuth;
+
+ // Constants
+
+ CT const ep = spheroid_const.m_ep;
+ CT const f = formula::flattening<CT>(spheroid_const.m_spheroid);
+ CT const one_minus_f = CT(1) - f;
+ std::size_t const series_order_plus_one = SeriesOrder + 1;
+ std::size_t const series_order_plus_two = SeriesOrder + 2;
+
+ // Basic trigonometric computations
+
+ CT tan_bet1 = tan(get_as_radian<1>(p1)) * one_minus_f;
+ CT tan_bet2 = tan(get_as_radian<1>(p2)) * one_minus_f;
+ CT cos_bet1 = cos(atan(tan_bet1));
+ CT cos_bet2 = cos(atan(tan_bet2));
+ CT sin_bet1 = tan_bet1 * cos_bet1;
+ CT sin_bet2 = tan_bet2 * cos_bet2;
+ CT sin_alp1 = sin(alp1);
+ CT cos_alp1 = cos(alp1);
+ CT cos_alp2 = cos(alp2);
+ CT sin_alp0 = sin_alp1 * cos_bet1;
+
+ // Spherical term computation
+
+ CT sin_omg1 = sin_alp0 * sin_bet1;
+ CT cos_omg1 = cos_alp1 * cos_bet1;
+ CT sin_omg2 = sin_alp0 * sin_bet2;
+ CT cos_omg2 = cos_alp2 * cos_bet2;
+ CT cos_omg12 = cos_omg1 * cos_omg2 + sin_omg1 * sin_omg2;
+ CT excess;
+
+ bool meridian = get<0>(p2) - get<0>(p1) == CT(0)
+ || get<1>(p1) == CT(90) || get<1>(p1) == -CT(90)
+ || get<1>(p2) == CT(90) || get<1>(p2) == -CT(90);
+
+ if (!meridian && cos_omg12 > -CT(0.7)
+ && sin_bet2 - sin_bet1 < CT(1.75)) // short segment
+ {
+ CT sin_omg12 = cos_omg1 * sin_omg2 - sin_omg1 * cos_omg2;
+ normalize(sin_omg12, cos_omg12);
+
+ CT cos_omg12p1 = CT(1) + cos_omg12;
+ CT cos_bet1p1 = CT(1) + cos_bet1;
+ CT cos_bet2p1 = CT(1) + cos_bet2;
+ excess = CT(2) * atan2(sin_omg12 * (sin_bet1 * cos_bet2p1 + sin_bet2 * cos_bet1p1),
+ cos_omg12p1 * (sin_bet1 * sin_bet2 + cos_bet1p1 * cos_bet2p1));
+ }
+ else
+ {
+ /*
+ CT sin_alp2 = sin(alp2);
+ CT sin_alp12 = sin_alp2 * cos_alp1 - cos_alp2 * sin_alp1;
+ CT cos_alp12 = cos_alp2 * cos_alp1 + sin_alp2 * sin_alp1;
+ excess = atan2(sin_alp12, cos_alp12);
+ */
+ excess = alp2 - alp1;
+ }
+
+ result.spherical_term = excess;
+
+ // Ellipsoidal term computation (uses integral approximation)
+
+ CT cos_alp0 = math::sqrt(CT(1) - math::sqr(sin_alp0));
+ CT cos_sig1 = cos_alp1 * cos_bet1;
+ CT cos_sig2 = cos_alp2 * cos_bet2;
+ CT sin_sig1 = sin_bet1;
+ CT sin_sig2 = sin_bet2;
+
+ normalize(sin_sig1, cos_sig1);
+ normalize(sin_sig2, cos_sig2);
+
+ CT coeffs[SeriesOrder + 1];
+ const std::size_t coeffs_var_size = (series_order_plus_two
+ * series_order_plus_one) / 2;
+ CT coeffs_var[coeffs_var_size];
+
+ if(ExpandEpsN){ // expand by eps and n
+
+ CT k2 = math::sqr(ep * cos_alp0);
+ CT sqrt_k2_plus_one = math::sqrt(CT(1) + k2);
+ CT eps = (sqrt_k2_plus_one - CT(1)) / (sqrt_k2_plus_one + CT(1));
+ CT n = f / (CT(2) - f);
+
+ // Generate and evaluate the polynomials on n
+ // to get the series coefficients (that depend on eps)
+ evaluate_coeffs_n(n, coeffs_var);
+
+ // Generate and evaluate the polynomials on eps (i.e. var2 = eps)
+ // to get the final series coefficients
+ evaluate_coeffs_var2(eps, coeffs_var, coeffs);
+
+ }else{ // expand by k2 and ep
+
+ CT k2 = math::sqr(ep * cos_alp0);
+ CT ep2 = math::sqr(ep);
+
+ // Generate and evaluate the polynomials on ep2
+ evaluate_coeffs_ep(ep2, coeffs_var);
+
+ // Generate and evaluate the polynomials on k2 (i.e. var2 = k2)
+ evaluate_coeffs_var2(k2, coeffs_var, coeffs);
+
+ }
+
+ // Evaluate the trigonometric sum
+ CT I12 = clenshaw_sum(cos_sig2, coeffs, coeffs + series_order_plus_one)
+ - clenshaw_sum(cos_sig1, coeffs, coeffs + series_order_plus_one);
+
+ // The part of the ellipsodal correction that depends on
+ // point coordinates
+ result.ellipsoidal_term = cos_alp0 * sin_alp0 * I12;
+
+ return result;
+ }
+
+ // Keep track whenever a segment crosses the prime meridian
+ // First normalize to [0,360)
+ template <typename PointOfSegment, typename StateType>
+ static inline int crosses_prime_meridian(PointOfSegment const& p1,
+ PointOfSegment const& p2,
+ StateType& state)
+ {
+ CT const pi
+ = geometry::math::pi<CT>();
+ CT const two_pi
+ = geometry::math::two_pi<CT>();
+
+ CT p1_lon = get_as_radian<0>(p1)
+ - ( floor( get_as_radian<0>(p1) / two_pi )
+ * two_pi );
+ CT p2_lon = get_as_radian<0>(p2)
+ - ( floor( get_as_radian<0>(p2) / two_pi )
+ * two_pi );
+
+ CT max_lon = (std::max)(p1_lon, p2_lon);
+ CT min_lon = (std::min)(p1_lon, p2_lon);
+
+ if(max_lon > pi && min_lon < pi && max_lon - min_lon > pi)
+ {
+ state.m_crosses_prime_meridian++;
+ }
+
+ return state.m_crosses_prime_meridian;
+ }
+
+};
+
+}}} // namespace boost::geometry::formula
+
+
+#endif // BOOST_GEOMETRY_FORMULAS_AREA_FORMULAS_HPP
diff --git a/boost/geometry/formulas/differential_quantities.hpp b/boost/geometry/formulas/differential_quantities.hpp
index 9a92f14e18..ff2ec539db 100644
--- a/boost/geometry/formulas/differential_quantities.hpp
+++ b/boost/geometry/formulas/differential_quantities.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2016 Oracle and/or its affiliates.
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -64,8 +64,8 @@ public:
CT const c1 = 1;
CT const one_minus_f = c1 - f;
- CT const sin_bet1 = one_minus_f * sin_lat1;
- CT const sin_bet2 = one_minus_f * sin_lat2;
+ CT sin_bet1 = one_minus_f * sin_lat1;
+ CT sin_bet2 = one_minus_f * sin_lat2;
// equator
if (math::equals(sin_bet1, c0) && math::equals(sin_bet2, c0))
@@ -89,14 +89,17 @@ public:
CT const e2 = f * (c2 - f);
CT const ep2 = e2 / math::sqr(one_minus_f);
- CT const cos_bet1 = cos_lat1;
- CT const cos_bet2 = cos_lat2;
-
CT const sin_alp1 = sin(azimuth);
CT const cos_alp1 = cos(azimuth);
//CT const sin_alp2 = sin(reverse_azimuth);
CT const cos_alp2 = cos(reverse_azimuth);
+ CT cos_bet1 = cos_lat1;
+ CT cos_bet2 = cos_lat2;
+
+ normalize(sin_bet1, cos_bet1);
+ normalize(sin_bet2, cos_bet2);
+
CT sin_sig1 = sin_bet1;
CT cos_sig1 = cos_alp1 * cos_bet1;
CT sin_sig2 = sin_bet2;
@@ -112,8 +115,8 @@ public:
J12_f(sin_sig1, cos_sig1, sin_sig2, cos_sig2, cos_alp0_sqr, f) :
J12_ep_sqr(sin_sig1, cos_sig1, sin_sig2, cos_sig2, cos_alp0_sqr, ep2) ;
- CT const dn1 = math::sqrt(c1 + e2 * math::sqr(sin_lat1));
- CT const dn2 = math::sqrt(c1 + e2 * math::sqr(sin_lat2));
+ CT const dn1 = math::sqrt(c1 + ep2 * math::sqr(sin_bet1));
+ CT const dn2 = math::sqrt(c1 + ep2 * math::sqr(sin_bet2));
if (BOOST_GEOMETRY_CONDITION(EnableReducedLength))
{
diff --git a/boost/geometry/formulas/eccentricity_sqr.hpp b/boost/geometry/formulas/eccentricity_sqr.hpp
new file mode 100644
index 0000000000..01a9beacb9
--- /dev/null
+++ b/boost/geometry/formulas/eccentricity_sqr.hpp
@@ -0,0 +1,70 @@
+// Boost.Geometry
+
+// Copyright (c) 2016 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_FORMULAS_ECCENCRICITY_SQR_HPP
+#define BOOST_GEOMETRY_FORMULAS_ECCENCRICITY_SQR_HPP
+
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace formula_dispatch
+{
+
+template <typename ResultType, typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct eccentricity_sqr
+ : not_implemented<Tag>
+{};
+
+template <typename ResultType, typename Geometry>
+struct eccentricity_sqr<ResultType, Geometry, srs_sphere_tag>
+{
+ static inline ResultType apply(Geometry const& /*geometry*/)
+ {
+ return ResultType(0);
+ }
+};
+
+template <typename ResultType, typename Geometry>
+struct eccentricity_sqr<ResultType, Geometry, srs_spheroid_tag>
+{
+ static inline ResultType apply(Geometry const& geometry)
+ {
+ // 1 - (b / a)^2
+ return ResultType(1) - math::sqr(ResultType(get_radius<2>(geometry))
+ / ResultType(get_radius<0>(geometry)));
+ }
+};
+
+} // namespace formula_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace formula
+{
+
+template <typename ResultType, typename Geometry>
+ResultType eccentricity_sqr(Geometry const& geometry)
+{
+ return formula_dispatch::eccentricity_sqr<ResultType, Geometry>::apply(geometry);
+}
+
+} // namespace formula
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_FORMULAS_ECCENCRICITY_SQR_HPP
diff --git a/boost/geometry/algorithms/detail/flattening.hpp b/boost/geometry/formulas/flattening.hpp
index 8ed5fd9a89..f94ead65b0 100644
--- a/boost/geometry/algorithms/detail/flattening.hpp
+++ b/boost/geometry/formulas/flattening.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2014 Oracle and/or its affiliates.
+// Copyright (c) 2014-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -8,8 +8,8 @@
// 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_FLATTENING_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP
+#ifndef BOOST_GEOMETRY_FORMULAS_FLATTENING_HPP
+#define BOOST_GEOMETRY_FORMULAS_FLATTENING_HPP
#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/core/tag.hpp>
@@ -21,7 +21,7 @@ namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
-namespace detail_dispatch
+namespace formula_dispatch
{
template <typename ResultType, typename Geometry, typename Tag = typename tag<Geometry>::type>
@@ -43,27 +43,28 @@ struct flattening<ResultType, Geometry, srs_spheroid_tag>
{
static inline ResultType apply(Geometry const& geometry)
{
+ // (a - b) / a
return ResultType(get_radius<0>(geometry) - get_radius<2>(geometry))
/ ResultType(get_radius<0>(geometry));
}
};
-} // namespace detail_dispatch
+} // namespace formula_dispatch
#endif // DOXYGEN_NO_DISPATCH
#ifndef DOXYGEN_NO_DETAIL
-namespace detail
+namespace formula
{
template <typename ResultType, typename Geometry>
ResultType flattening(Geometry const& geometry)
{
- return detail_dispatch::flattening<ResultType, Geometry>::apply(geometry);
+ return formula_dispatch::flattening<ResultType, Geometry>::apply(geometry);
}
-} // namespace detail
+} // namespace formula
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP
+#endif // BOOST_GEOMETRY_FORMULAS_FLATTENING_HPP
diff --git a/boost/geometry/formulas/geographic.hpp b/boost/geometry/formulas/geographic.hpp
new file mode 100644
index 0000000000..f6feb66633
--- /dev/null
+++ b/boost/geometry/formulas/geographic.hpp
@@ -0,0 +1,457 @@
+// Boost.Geometry
+
+// Copyright (c) 2016, 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_FORMULAS_GEOGRAPHIC_HPP
+#define BOOST_GEOMETRY_FORMULAS_GEOGRAPHIC_HPP
+
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/arithmetic/cross_product.hpp>
+#include <boost/geometry/arithmetic/dot_product.hpp>
+#include <boost/geometry/arithmetic/normalize.hpp>
+
+#include <boost/geometry/formulas/eccentricity_sqr.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+namespace boost { namespace geometry {
+
+namespace formula {
+
+template <typename Point3d, typename PointGeo, typename Spheroid>
+inline Point3d geo_to_cart3d(PointGeo const& point_geo, Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type calc_t;
+
+ calc_t const c1 = 1;
+ calc_t const e_sqr = eccentricity_sqr<calc_t>(spheroid);
+
+ calc_t const lon = get_as_radian<0>(point_geo);
+ calc_t const lat = get_as_radian<1>(point_geo);
+
+ Point3d res;
+
+ calc_t const sin_lat = sin(lat);
+
+ // "unit" spheroid, a = 1
+ calc_t const N = c1 / math::sqrt(c1 - e_sqr * math::sqr(sin_lat));
+ calc_t const N_cos_lat = N * cos(lat);
+
+ set<0>(res, N_cos_lat * cos(lon));
+ set<1>(res, N_cos_lat * sin(lon));
+ set<2>(res, N * (c1 - e_sqr) * sin_lat);
+
+ return res;
+}
+
+template <typename PointGeo, typename Spheroid, typename Point3d>
+inline void geo_to_cart3d(PointGeo const& point_geo, Point3d & result, Point3d & north, Point3d & east, Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type calc_t;
+
+ calc_t const c1 = 1;
+ calc_t const e_sqr = eccentricity_sqr<calc_t>(spheroid);
+
+ calc_t const lon = get_as_radian<0>(point_geo);
+ calc_t const lat = get_as_radian<1>(point_geo);
+
+ calc_t const sin_lon = sin(lon);
+ calc_t const cos_lon = cos(lon);
+ calc_t const sin_lat = sin(lat);
+ calc_t const cos_lat = cos(lat);
+
+ // "unit" spheroid, a = 1
+ calc_t const N = c1 / math::sqrt(c1 - e_sqr * math::sqr(sin_lat));
+ calc_t const N_cos_lat = N * cos_lat;
+
+ set<0>(result, N_cos_lat * cos_lon);
+ set<1>(result, N_cos_lat * sin_lon);
+ set<2>(result, N * (c1 - e_sqr) * sin_lat);
+
+ set<0>(east, -sin_lon);
+ set<1>(east, cos_lon);
+ set<2>(east, 0);
+
+ set<0>(north, -sin_lat * cos_lon);
+ set<1>(north, -sin_lat * sin_lon);
+ set<2>(north, cos_lat);
+}
+
+template <typename PointGeo, typename Point3d, typename Spheroid>
+inline PointGeo cart3d_to_geo(Point3d const& point_3d, Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<PointGeo>::type coord_t;
+ typedef typename coordinate_type<Point3d>::type calc_t;
+
+ calc_t const c1 = 1;
+ //calc_t const c2 = 2;
+ calc_t const e_sqr = eccentricity_sqr<calc_t>(spheroid);
+
+ calc_t const x = get<0>(point_3d);
+ calc_t const y = get<1>(point_3d);
+ calc_t const z = get<2>(point_3d);
+ calc_t const xy_l = math::sqrt(math::sqr(x) + math::sqr(y));
+
+ calc_t const lonr = atan2(y, x);
+
+ // NOTE: Alternative version
+ // http://www.iag-aig.org/attach/989c8e501d9c5b5e2736955baf2632f5/V60N2_5FT.pdf
+ // calc_t const lonr = c2 * atan2(y, x + xy_l);
+
+ calc_t const latr = atan2(z, (c1 - e_sqr) * xy_l);
+
+ // NOTE: If h is equal to 0 then there is no need to improve value of latitude
+ // because then N_i / (N_i + h_i) = 1
+ // http://www.navipedia.net/index.php/Ellipsoidal_and_Cartesian_Coordinates_Conversion
+
+ PointGeo res;
+
+ set_from_radian<0>(res, lonr);
+ set_from_radian<1>(res, latr);
+
+ coord_t lon = get<0>(res);
+ coord_t lat = get<1>(res);
+
+ math::normalize_spheroidal_coordinates
+ <
+ typename coordinate_system<PointGeo>::type::units,
+ coord_t
+ >(lon, lat);
+
+ set<0>(res, lon);
+ set<1>(res, lat);
+
+ return res;
+}
+
+template <typename Point3d, typename Spheroid>
+inline Point3d projected_to_xy(Point3d const& point_3d, Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ // len_xy = sqrt(x^2 + y^2)
+ // r = len_xy - |z / tan(lat)|
+ // assuming h = 0
+ // lat = atan2(z, (1 - e^2) * len_xy);
+ // |z / tan(lat)| = (1 - e^2) * len_xy
+ // r = e^2 * len_xy
+ // x_res = r * cos(lon) = e^2 * len_xy * x / len_xy = e^2 * x
+ // y_res = r * sin(lon) = e^2 * len_xy * y / len_xy = e^2 * y
+
+ coord_t const c0 = 0;
+ coord_t const e_sqr = formula::eccentricity_sqr<coord_t>(spheroid);
+
+ Point3d res;
+
+ set<0>(res, e_sqr * get<0>(point_3d));
+ set<1>(res, e_sqr * get<1>(point_3d));
+ set<2>(res, c0);
+
+ return res;
+}
+
+template <typename Point3d, typename Spheroid>
+inline Point3d projected_to_surface(Point3d const& direction, Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ //coord_t const c0 = 0;
+ coord_t const c2 = 2;
+ coord_t const c4 = 4;
+
+ // calculate the point of intersection of a ray and spheroid's surface
+ // the origin is the origin of the coordinate system
+ //(x*x+y*y)/(a*a) + z*z/(b*b) = 1
+ // x = d.x * t
+ // y = d.y * t
+ // z = d.z * t
+ coord_t const dx = get<0>(direction);
+ coord_t const dy = get<1>(direction);
+ coord_t const dz = get<2>(direction);
+
+ //coord_t const a_sqr = math::sqr(get_radius<0>(spheroid));
+ //coord_t const b_sqr = math::sqr(get_radius<2>(spheroid));
+ // "unit" spheroid, a = 1
+ coord_t const a_sqr = 1;
+ coord_t const b_sqr = math::sqr(get_radius<2>(spheroid) / get_radius<0>(spheroid));
+
+ coord_t const param_a = (dx*dx + dy*dy) / a_sqr + dz*dz / b_sqr;
+ coord_t const delta = c4 * param_a;
+ // delta >= 0
+ coord_t const t = math::sqrt(delta) / (c2 * param_a);
+
+ // result = direction * t
+ Point3d result = direction;
+ multiply_value(result, t);
+
+ return result;
+}
+
+template <typename Point3d, typename Spheroid>
+inline bool projected_to_surface(Point3d const& origin, Point3d const& direction, Point3d & result1, Point3d & result2, Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ coord_t const c0 = 0;
+ coord_t const c1 = 1;
+ coord_t const c2 = 2;
+ coord_t const c4 = 4;
+
+ // calculate the point of intersection of a ray and spheroid's surface
+ //(x*x+y*y)/(a*a) + z*z/(b*b) = 1
+ // x = o.x + d.x * t
+ // y = o.y + d.y * t
+ // z = o.z + d.z * t
+ coord_t const ox = get<0>(origin);
+ coord_t const oy = get<1>(origin);
+ coord_t const oz = get<2>(origin);
+ coord_t const dx = get<0>(direction);
+ coord_t const dy = get<1>(direction);
+ coord_t const dz = get<2>(direction);
+
+ //coord_t const a_sqr = math::sqr(get_radius<0>(spheroid));
+ //coord_t const b_sqr = math::sqr(get_radius<2>(spheroid));
+ // "unit" spheroid, a = 1
+ coord_t const a_sqr = 1;
+ coord_t const b_sqr = math::sqr(get_radius<2>(spheroid) / get_radius<0>(spheroid));
+
+ coord_t const param_a = (dx*dx + dy*dy) / a_sqr + dz*dz / b_sqr;
+ coord_t const param_b = c2 * ((ox*dx + oy*dy) / a_sqr + oz*dz / b_sqr);
+ coord_t const param_c = (ox*ox + oy*oy) / a_sqr + oz*oz / b_sqr - c1;
+
+ coord_t const delta = math::sqr(param_b) - c4 * param_a*param_c;
+
+ // equals() ?
+ if (delta < c0 || param_a == 0)
+ {
+ return false;
+ }
+
+ // result = origin + direction * t
+
+ coord_t const sqrt_delta = math::sqrt(delta);
+ coord_t const two_a = c2 * param_a;
+
+ coord_t const t1 = (-param_b + sqrt_delta) / two_a;
+ result1 = direction;
+ multiply_value(result1, t1);
+ add_point(result1, origin);
+
+ coord_t const t2 = (-param_b - sqrt_delta) / two_a;
+ result2 = direction;
+ multiply_value(result2, t2);
+ add_point(result2, origin);
+
+ return true;
+}
+
+template <typename Point3d, typename Spheroid>
+inline bool great_elliptic_intersection(Point3d const& a1, Point3d const& a2,
+ Point3d const& b1, Point3d const& b2,
+ Point3d & result,
+ Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ coord_t c0 = 0;
+ coord_t c1 = 1;
+
+ Point3d n1 = cross_product(a1, a2);
+ Point3d n2 = cross_product(b1, b2);
+
+ // intersection direction
+ Point3d id = cross_product(n1, n2);
+ coord_t id_len_sqr = dot_product(id, id);
+
+ if (math::equals(id_len_sqr, c0))
+ {
+ return false;
+ }
+
+ // no need to normalize a1 and a2 because the intersection point on
+ // the opposite side of the globe is at the same distance from the origin
+ coord_t cos_a1i = dot_product(a1, id);
+ coord_t cos_a2i = dot_product(a2, id);
+ coord_t gri = math::detail::greatest(cos_a1i, cos_a2i);
+ Point3d neg_id = id;
+ multiply_value(neg_id, -c1);
+ coord_t cos_a1ni = dot_product(a1, neg_id);
+ coord_t cos_a2ni = dot_product(a2, neg_id);
+ coord_t grni = math::detail::greatest(cos_a1ni, cos_a2ni);
+
+ if (gri >= grni)
+ {
+ result = projected_to_surface(id, spheroid);
+ }
+ else
+ {
+ result = projected_to_surface(neg_id, spheroid);
+ }
+
+ return true;
+}
+
+template <typename Point3d1, typename Point3d2>
+static inline int elliptic_side_value(Point3d1 const& origin, Point3d1 const& norm, Point3d2 const& pt)
+{
+ typedef typename coordinate_type<Point3d1>::type calc_t;
+ calc_t c0 = 0;
+
+ // vector oposite to pt - origin
+ // only for the purpose of assigning origin
+ Point3d1 vec = origin;
+ subtract_point(vec, pt);
+
+ calc_t d = dot_product(norm, vec);
+
+ // since the vector is opposite the signs are opposite
+ return math::equals(d, c0) ? 0
+ : d < c0 ? 1
+ : -1; // d > 0
+}
+
+template <typename Point3d, typename Spheroid>
+inline bool planes_spheroid_intersection(Point3d const& o1, Point3d const& n1,
+ Point3d const& o2, Point3d const& n2,
+ Point3d & ip1, Point3d & ip2,
+ Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ coord_t c0 = 0;
+ coord_t c1 = 1;
+
+ // Below
+ // n . (p - o) = 0
+ // n . p - n . o = 0
+ // n . p + d = 0
+ // n . p = h
+
+ // intersection direction
+ Point3d id = cross_product(n1, n2);
+
+ if (math::equals(dot_product(id, id), c0))
+ {
+ return false;
+ }
+
+ coord_t dot_n1_n2 = dot_product(n1, n2);
+ coord_t dot_n1_n2_sqr = math::sqr(dot_n1_n2);
+
+ coord_t h1 = dot_product(n1, o1);
+ coord_t h2 = dot_product(n2, o2);
+
+ coord_t denom = c1 - dot_n1_n2_sqr;
+ coord_t C1 = (h1 - h2 * dot_n1_n2) / denom;
+ coord_t C2 = (h2 - h1 * dot_n1_n2) / denom;
+
+ // C1 * n1 + C2 * n2
+ Point3d C1_n1 = n1;
+ multiply_value(C1_n1, C1);
+ Point3d C2_n2 = n2;
+ multiply_value(C2_n2, C2);
+ Point3d io = C1_n1;
+ add_point(io, C2_n2);
+
+ if (! projected_to_surface(io, id, ip1, ip2, spheroid))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+template <typename Point3d, typename Spheroid>
+inline void experimental_elliptic_plane(Point3d const& p1, Point3d const& p2,
+ Point3d & v1, Point3d & v2,
+ Point3d & origin, Point3d & normal,
+ Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ Point3d xy1 = projected_to_xy(p1, spheroid);
+ Point3d xy2 = projected_to_xy(p2, spheroid);
+
+ // origin = (xy1 + xy2) / 2
+ origin = xy1;
+ add_point(origin, xy2);
+ multiply_value(origin, coord_t(0.5));
+
+ // v1 = p1 - origin
+ v1 = p1;
+ subtract_point(v1, origin);
+ // v2 = p2 - origin
+ v2 = p2;
+ subtract_point(v2, origin);
+
+ normal = cross_product(v1, v2);
+}
+
+template <typename Point3d, typename Spheroid>
+inline void experimental_elliptic_plane(Point3d const& p1, Point3d const& p2,
+ Point3d & origin, Point3d & normal,
+ Spheroid const& spheroid)
+{
+ Point3d v1, v2;
+ experimental_elliptic_plane(p1, p2, v1, v2, origin, normal, spheroid);
+}
+
+template <typename Point3d, typename Spheroid>
+inline bool experimental_elliptic_intersection(Point3d const& a1, Point3d const& a2,
+ Point3d const& b1, Point3d const& b2,
+ Point3d & result,
+ Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ coord_t c0 = 0;
+ coord_t c1 = 1;
+
+ Point3d a1v, a2v, o1, n1;
+ experimental_elliptic_plane(a1, a2, a1v, a2v, o1, n1, spheroid);
+ Point3d b1v, b2v, o2, n2;
+ experimental_elliptic_plane(b1, b2, b1v, b2v, o2, n2, spheroid);
+
+ if (! detail::vec_normalize(n1) || ! detail::vec_normalize(n2))
+ {
+ return false;
+ }
+
+ Point3d ip1_s, ip2_s;
+ if (! planes_spheroid_intersection(o1, n1, o2, n2, ip1_s, ip2_s, spheroid))
+ {
+ return false;
+ }
+
+ // NOTE: simplified test, may not work in all cases
+ coord_t dot_a1i1 = dot_product(a1, ip1_s);
+ coord_t dot_a2i1 = dot_product(a2, ip1_s);
+ coord_t gri1 = math::detail::greatest(dot_a1i1, dot_a2i1);
+ coord_t dot_a1i2 = dot_product(a1, ip2_s);
+ coord_t dot_a2i2 = dot_product(a2, ip2_s);
+ coord_t gri2 = math::detail::greatest(dot_a1i2, dot_a2i2);
+
+ result = gri1 >= gri2 ? ip1_s : ip2_s;
+
+ return true;
+}
+
+} // namespace formula
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_FORMULAS_GEOGRAPHIC_HPP
diff --git a/boost/geometry/formulas/gnomonic_spheroid.hpp b/boost/geometry/formulas/gnomonic_spheroid.hpp
index 3457397b0f..4710c6c063 100644
--- a/boost/geometry/formulas/gnomonic_spheroid.hpp
+++ b/boost/geometry/formulas/gnomonic_spheroid.hpp
@@ -14,12 +14,11 @@
#include <boost/geometry/core/radius.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/formulas/andoyer_inverse.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/thomas_inverse.hpp>
#include <boost/geometry/formulas/vincenty_direct.hpp>
#include <boost/geometry/formulas/vincenty_inverse.hpp>
diff --git a/boost/geometry/formulas/sjoberg_intersection.hpp b/boost/geometry/formulas/sjoberg_intersection.hpp
index 03bd4bc97e..92f9e8e78e 100644
--- a/boost/geometry/formulas/sjoberg_intersection.hpp
+++ b/boost/geometry/formulas/sjoberg_intersection.hpp
@@ -20,19 +20,606 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
+#include <boost/geometry/formulas/spherical.hpp>
namespace boost { namespace geometry { namespace formula
{
/*!
+\brief The intersection of two great circles as proposed by Sjoberg.
+\see See
+ - [Sjoberg02] Lars E. Sjoberg, Intersections on the sphere and ellipsoid, 2002
+ http://link.springer.com/article/10.1007/s00190-001-0230-9
+*/
+template <typename CT>
+struct sjoberg_intersection_spherical_02
+{
+ // TODO: if it will be used as standalone formula
+ // support segments on equator and endpoints on poles
+
+ static inline bool apply(CT const& lon1, CT const& lat1, CT const& lon_a2, CT const& lat_a2,
+ CT const& lon2, CT const& lat2, CT const& lon_b2, CT const& lat_b2,
+ CT & lon, CT & lat)
+ {
+ CT tan_lat = 0;
+ bool res = apply_alt(lon1, lat1, lon_a2, lat_a2,
+ lon2, lat2, lon_b2, lat_b2,
+ lon, tan_lat);
+
+ if (res)
+ {
+ lat = atan(tan_lat);
+ }
+
+ return res;
+ }
+
+ static inline bool apply_alt(CT const& lon1, CT const& lat1, CT const& lon_a2, CT const& lat_a2,
+ CT const& lon2, CT const& lat2, CT const& lon_b2, CT const& lat_b2,
+ CT & lon, CT & tan_lat)
+ {
+ CT const cos_lon1 = cos(lon1);
+ CT const sin_lon1 = sin(lon1);
+ CT const cos_lon2 = cos(lon2);
+ CT const sin_lon2 = sin(lon2);
+ CT const sin_lat1 = sin(lat1);
+ CT const sin_lat2 = sin(lat2);
+ CT const cos_lat1 = cos(lat1);
+ CT const cos_lat2 = cos(lat2);
+
+ CT const tan_lat_a2 = tan(lat_a2);
+ CT const tan_lat_b2 = tan(lat_b2);
+
+ return apply(lon1, lon_a2, lon2, lon_b2,
+ sin_lon1, cos_lon1, sin_lat1, cos_lat1,
+ sin_lon2, cos_lon2, sin_lat2, cos_lat2,
+ tan_lat_a2, tan_lat_b2,
+ lon, tan_lat);
+ }
+
+private:
+ static inline bool apply(CT const& lon1, CT const& lon_a2, CT const& lon2, CT const& lon_b2,
+ CT const& sin_lon1, CT const& cos_lon1, CT const& sin_lat1, CT const& cos_lat1,
+ CT const& sin_lon2, CT const& cos_lon2, CT const& sin_lat2, CT const& cos_lat2,
+ CT const& tan_lat_a2, CT const& tan_lat_b2,
+ CT & lon, CT & tan_lat)
+ {
+ // NOTE:
+ // cos_lat_ = 0 <=> segment on equator
+ // tan_alpha_ = 0 <=> segment vertical
+
+ CT const tan_lat1 = sin_lat1 / cos_lat1; //tan(lat1);
+ CT const tan_lat2 = sin_lat2 / cos_lat2; //tan(lat2);
+
+ CT const dlon1 = lon_a2 - lon1;
+ CT const sin_dlon1 = sin(dlon1);
+ CT const dlon2 = lon_b2 - lon2;
+ CT const sin_dlon2 = sin(dlon2);
+
+ CT const c0 = 0;
+ bool const is_vertical1 = math::equals(sin_dlon1, c0);
+ bool const is_vertical2 = math::equals(sin_dlon2, c0);
+
+ CT tan_alpha1 = 0;
+ CT tan_alpha2 = 0;
+
+ if (is_vertical1 && is_vertical2)
+ {
+ // circles intersect at one of the poles or are collinear
+ return false;
+ }
+ else if (is_vertical1)
+ {
+ CT const cos_dlon2 = cos(dlon2);
+ CT const tan_alpha2_x = cos_lat2 * tan_lat_b2 - sin_lat2 * cos_dlon2;
+ tan_alpha2 = sin_dlon2 / tan_alpha2_x;
+
+ lon = lon1;
+ }
+ else if (is_vertical2)
+ {
+ CT const cos_dlon1 = cos(dlon1);
+ CT const tan_alpha1_x = cos_lat1 * tan_lat_a2 - sin_lat1 * cos_dlon1;
+ tan_alpha1 = sin_dlon1 / tan_alpha1_x;
+
+ lon = lon2;
+ }
+ else
+ {
+ CT const cos_dlon1 = cos(dlon1);
+ CT const cos_dlon2 = cos(dlon2);
+
+ CT const tan_alpha1_x = cos_lat1 * tan_lat_a2 - sin_lat1 * cos_dlon1;
+ CT const tan_alpha2_x = cos_lat2 * tan_lat_b2 - sin_lat2 * cos_dlon2;
+ tan_alpha1 = sin_dlon1 / tan_alpha1_x;
+ tan_alpha2 = sin_dlon2 / tan_alpha2_x;
+
+ CT const T1 = tan_alpha1 * cos_lat1;
+ CT const T2 = tan_alpha2 * cos_lat2;
+ CT const T1T2 = T1*T2;
+ CT const tan_lon_y = T1 * sin_lon2 - T2 * sin_lon1 + T1T2 * (tan_lat1 * cos_lon1 - tan_lat2 * cos_lon2);
+ CT const tan_lon_x = T1 * cos_lon2 - T2 * cos_lon1 - T1T2 * (tan_lat1 * sin_lon1 - tan_lat2 * sin_lon2);
+
+ lon = atan2(tan_lon_y, tan_lon_x);
+ }
+
+ // choose closer result
+ CT const pi = math::pi<CT>();
+ CT const lon_2 = lon > c0 ? lon - pi : lon + pi;
+ CT const lon_dist1 = (std::max)((std::min)(math::longitude_difference<radian>(lon1, lon),
+ math::longitude_difference<radian>(lon_a2, lon)),
+ (std::min)(math::longitude_difference<radian>(lon2, lon),
+ math::longitude_difference<radian>(lon_b2, lon)));
+ CT const lon_dist2 = (std::max)((std::min)(math::longitude_difference<radian>(lon1, lon_2),
+ math::longitude_difference<radian>(lon_a2, lon_2)),
+ (std::min)(math::longitude_difference<radian>(lon2, lon_2),
+ math::longitude_difference<radian>(lon_b2, lon_2)));
+ if (lon_dist2 < lon_dist1)
+ {
+ lon = lon_2;
+ }
+
+ CT const sin_lon = sin(lon);
+ CT const cos_lon = cos(lon);
+
+ if (math::abs(tan_alpha1) >= math::abs(tan_alpha2)) // pick less vertical segment
+ {
+ CT const sin_dlon_1 = sin_lon * cos_lon1 - cos_lon * sin_lon1;
+ CT const cos_dlon_1 = cos_lon * cos_lon1 + sin_lon * sin_lon1;
+ CT const lat_y_1 = sin_dlon_1 + tan_alpha1 * sin_lat1 * cos_dlon_1;
+ CT const lat_x_1 = tan_alpha1 * cos_lat1;
+ tan_lat = lat_y_1 / lat_x_1;
+ }
+ else
+ {
+ CT const sin_dlon_2 = sin_lon * cos_lon2 - cos_lon * sin_lon2;
+ CT const cos_dlon_2 = cos_lon * cos_lon2 + sin_lon * sin_lon2;
+ CT const lat_y_2 = sin_dlon_2 + tan_alpha2 * sin_lat2 * cos_dlon_2;
+ CT const lat_x_2 = tan_alpha2 * cos_lat2;
+ tan_lat = lat_y_2 / lat_x_2;
+ }
+
+ return true;
+ }
+};
+
+
+/*! Approximation of dLambda_j [Sjoberg07], expanded into taylor series in e^2
+ Maxima script:
+ dLI_j(c_j, sinB_j, sinB) := integrate(1 / (sqrt(1 - c_j ^ 2 - x ^ 2)*(1 + sqrt(1 - e2*(1 - x ^ 2)))), x, sinB_j, sinB);
+ dL_j(c_j, B_j, B) := -e2 * c_j * dLI_j(c_j, B_j, B);
+ S: taylor(dLI_j(c_j, sinB_j, sinB), e2, 0, 3);
+ assume(c_j < 1);
+ assume(c_j > 0);
+ L1: factor(integrate(sqrt(-x ^ 2 - c_j ^ 2 + 1) / (x ^ 2 + c_j ^ 2 - 1), x));
+ L2: factor(integrate(((x ^ 2 - 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
+ L3: factor(integrate(((x ^ 4 - 2 * x ^ 2 + 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
+ L4: factor(integrate(((x ^ 6 - 3 * x ^ 4 + 3 * x ^ 2 - 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
+
+\see See
+ - [Sjoberg07] Lars E. Sjoberg, Geodetic intersection on the ellipsoid, 2007
+ http://link.springer.com/article/10.1007/s00190-007-0204-7
+*/
+template <unsigned int Order, typename CT>
+inline CT sjoberg_d_lambda_e_sqr(CT const& sin_betaj, CT const& sin_beta,
+ CT const& Cj, CT const& sqrt_1_Cj_sqr,
+ CT const& e_sqr)
+{
+ using math::detail::bounded;
+
+ if (Order == 0)
+ {
+ return 0;
+ }
+
+ CT const c1 = 1;
+ CT const c2 = 2;
+
+ CT const asin_B = asin(bounded(sin_beta / sqrt_1_Cj_sqr, -c1, c1));
+ CT const asin_Bj = asin(sin_betaj / sqrt_1_Cj_sqr);
+ CT const L0 = (asin_B - asin_Bj) / c2;
+
+ if (Order == 1)
+ {
+ return -Cj * e_sqr * L0;
+ }
+
+ CT const c0 = 0;
+ CT const c16 = 16;
+
+ CT const X = sin_beta;
+ CT const Xj = sin_betaj;
+ CT const X_sqr = math::sqr(X);
+ CT const Xj_sqr = math::sqr(Xj);
+ CT const Cj_sqr = math::sqr(Cj);
+ CT const Cj_sqr_plus_one = Cj_sqr + c1;
+ CT const one_minus_Cj_sqr = c1 - Cj_sqr;
+ CT const sqrt_Y = math::sqrt(bounded(-X_sqr + one_minus_Cj_sqr, c0));
+ CT const sqrt_Yj = math::sqrt(-Xj_sqr + one_minus_Cj_sqr);
+ CT const L1 = (Cj_sqr_plus_one * (asin_B - asin_Bj) + X * sqrt_Y - Xj * sqrt_Yj) / c16;
+
+ if (Order == 2)
+ {
+ return -Cj * e_sqr * (L0 + e_sqr * L1);
+ }
+
+ CT const c3 = 3;
+ CT const c5 = 5;
+ CT const c128 = 128;
+
+ CT const E = Cj_sqr * (c3 * Cj_sqr + c2) + c3;
+ CT const F = X * (-c2 * X_sqr + c3 * Cj_sqr + c5);
+ CT const Fj = Xj * (-c2 * Xj_sqr + c3 * Cj_sqr + c5);
+ CT const L2 = (E * (asin_B - asin_Bj) + F * sqrt_Y - Fj * sqrt_Yj) / c128;
+
+ if (Order == 3)
+ {
+ return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * L2));
+ }
+
+ CT const c8 = 8;
+ CT const c9 = 9;
+ CT const c10 = 10;
+ CT const c15 = 15;
+ CT const c24 = 24;
+ CT const c26 = 26;
+ CT const c33 = 33;
+ CT const c6144 = 6144;
+
+ CT const G = Cj_sqr * (Cj_sqr * (Cj_sqr * c15 + c9) + c9) + c15;
+ CT const H = -c10 * Cj_sqr - c26;
+ CT const I = Cj_sqr * (Cj_sqr * c15 + c24) + c33;
+ CT const J = X_sqr * (X * (c8 * X_sqr + H)) + X * I;
+ CT const Jj = Xj_sqr * (Xj * (c8 * Xj_sqr + H)) + Xj * I;
+ CT const L3 = (G * (asin_B - asin_Bj) + J * sqrt_Y - Jj * sqrt_Yj) / c6144;
+
+ // Order 4 and higher
+ return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * (L2 + e_sqr * L3)));
+}
+
+/*!
+\brief The representation of geodesic as proposed by Sjoberg.
+\see See
+ - [Sjoberg07] Lars E. Sjoberg, Geodetic intersection on the ellipsoid, 2007
+ http://link.springer.com/article/10.1007/s00190-007-0204-7
+ - [Sjoberg12] Lars E. Sjoberg, Solutions to the ellipsoidal Clairaut constant
+ and the inverse geodetic problem by numerical integration, 2012
+ https://www.degruyter.com/view/j/jogs.2012.2.issue-3/v10156-011-0037-4/v10156-011-0037-4.xml
+*/
+template <typename CT, unsigned int Order>
+class sjoberg_geodesic
+{
+ sjoberg_geodesic() {}
+
+ static int sign_C(CT const& alphaj)
+ {
+ CT const c0 = 0;
+ CT const c2 = 2;
+ CT const pi = math::pi<CT>();
+ CT const pi_half = pi / c2;
+
+ return (pi_half < alphaj && alphaj < pi) || (-pi_half < alphaj && alphaj < c0) ? -1 : 1;
+ }
+
+public:
+ sjoberg_geodesic(CT const& lon, CT const& lat, CT const& alpha, CT const& f)
+ : lonj(lon)
+ , latj(lat)
+ , alphaj(alpha)
+ {
+ CT const c0 = 0;
+ CT const c1 = 1;
+ CT const c2 = 2;
+ //CT const pi = math::pi<CT>();
+ //CT const pi_half = pi / c2;
+
+ one_minus_f = c1 - f;
+ e_sqr = f * (c2 - f);
+
+ tan_latj = tan(lat);
+ tan_betaj = one_minus_f * tan_latj;
+ betaj = atan(tan_betaj);
+ sin_betaj = sin(betaj);
+
+ cos_betaj = cos(betaj);
+ sin_alphaj = sin(alphaj);
+ // Clairaut constant (lower-case in the paper)
+ Cj = sign_C(alphaj) * cos_betaj * sin_alphaj;
+ Cj_sqr = math::sqr(Cj);
+ sqrt_1_Cj_sqr = math::sqrt(c1 - Cj_sqr);
+
+ sign_lon_diff = alphaj >= 0 ? 1 : -1; // || alphaj == -pi ?
+ //sign_lon_diff = 1;
+
+ is_on_equator = math::equals(sqrt_1_Cj_sqr, c0);
+ is_Cj_zero = math::equals(Cj, c0);
+
+ t0j = c0;
+ asin_tj_t0j = c0;
+
+ if (! is_Cj_zero)
+ {
+ t0j = sqrt_1_Cj_sqr / Cj;
+ }
+
+ if (! is_on_equator)
+ {
+ //asin_tj_t0j = asin(tan_betaj / t0j);
+ asin_tj_t0j = asin(tan_betaj * Cj / sqrt_1_Cj_sqr);
+ }
+ }
+
+ struct vertex_data
+ {
+ //CT beta0j;
+ CT sin_beta0j;
+ CT dL0j;
+ CT lon0j;
+ };
+
+ vertex_data get_vertex_data() const
+ {
+ CT const c2 = 2;
+ CT const pi = math::pi<CT>();
+ CT const pi_half = pi / c2;
+
+ vertex_data res;
+
+ if (! is_Cj_zero)
+ {
+ //res.beta0j = atan(t0j);
+ //res.sin_beta0j = sin(res.beta0j);
+ res.sin_beta0j = math::sign(t0j) * sqrt_1_Cj_sqr;
+ res.dL0j = d_lambda(res.sin_beta0j);
+ res.lon0j = lonj + sign_lon_diff * (pi_half - asin_tj_t0j + res.dL0j);
+ }
+ else
+ {
+ //res.beta0j = pi_half;
+ //res.sin_beta0j = betaj >= 0 ? 1 : -1;
+ res.sin_beta0j = 1;
+ res.dL0j = 0;
+ res.lon0j = lonj;
+ }
+
+ return res;
+ }
+
+ bool is_sin_beta_ok(CT const& sin_beta) const
+ {
+ CT const c1 = 1;
+ return math::abs(sin_beta / sqrt_1_Cj_sqr) <= c1;
+ }
+
+ bool k_diff(CT const& sin_beta,
+ CT & delta_k) const
+ {
+ if (is_Cj_zero)
+ {
+ delta_k = 0;
+ return true;
+ }
+
+ // beta out of bounds and not close
+ if (! (is_sin_beta_ok(sin_beta)
+ || math::equals(math::abs(sin_beta), sqrt_1_Cj_sqr)) )
+ {
+ return false;
+ }
+
+ // NOTE: beta may be slightly out of bounds here but d_lambda handles that
+ CT const dLj = d_lambda(sin_beta);
+ delta_k = sign_lon_diff * (/*asin_t_t0j*/ - asin_tj_t0j + dLj);
+
+ return true;
+ }
+
+ bool lon_diff(CT const& sin_beta, CT const& t,
+ CT & delta_lon) const
+ {
+ using math::detail::bounded;
+ CT const c1 = 1;
+
+ if (is_Cj_zero)
+ {
+ delta_lon = 0;
+ return true;
+ }
+
+ CT delta_k = 0;
+ if (! k_diff(sin_beta, delta_k))
+ {
+ return false;
+ }
+
+ CT const t_t0j = t / t0j;
+ // NOTE: t may be slightly out of bounds here
+ CT const asin_t_t0j = asin(bounded(t_t0j, -c1, c1));
+ delta_lon = sign_lon_diff * asin_t_t0j + delta_k;
+
+ return true;
+ }
+
+ bool k_diffs(CT const& sin_beta, vertex_data const& vd,
+ CT & delta_k_before, CT & delta_k_behind,
+ bool check_sin_beta = true) const
+ {
+ CT const pi = math::pi<CT>();
+
+ if (is_Cj_zero)
+ {
+ delta_k_before = 0;
+ delta_k_behind = sign_lon_diff * pi;
+ return true;
+ }
+
+ // beta out of bounds and not close
+ if (check_sin_beta
+ && ! (is_sin_beta_ok(sin_beta)
+ || math::equals(math::abs(sin_beta), sqrt_1_Cj_sqr)) )
+ {
+ return false;
+ }
+
+ // NOTE: beta may be slightly out of bounds here but d_lambda handles that
+ CT const dLj = d_lambda(sin_beta);
+ delta_k_before = sign_lon_diff * (/*asin_t_t0j*/ - asin_tj_t0j + dLj);
+
+ // This version require no additional dLj calculation
+ delta_k_behind = sign_lon_diff * (pi /*- asin_t_t0j*/ - asin_tj_t0j + vd.dL0j + (vd.dL0j - dLj));
+
+ // [Sjoberg12]
+ //CT const dL101 = d_lambda(sin_betaj, vd.sin_beta0j);
+ // WARNING: the following call might not work if beta was OoB because only the second argument is bounded
+ //CT const dL_01 = d_lambda(sin_beta, vd.sin_beta0j);
+ //delta_k_behind = sign_lon_diff * (pi /*- asin_t_t0j*/ - asin_tj_t0j + dL101 + dL_01);
+
+ return true;
+ }
+
+ bool lon_diffs(CT const& sin_beta, CT const& t, vertex_data const& vd,
+ CT & delta_lon_before, CT & delta_lon_behind) const
+ {
+ using math::detail::bounded;
+ CT const c1 = 1;
+ CT const pi = math::pi<CT>();
+
+ if (is_Cj_zero)
+ {
+ delta_lon_before = 0;
+ delta_lon_behind = sign_lon_diff * pi;
+ return true;
+ }
+
+ CT delta_k_before = 0, delta_k_behind = 0;
+ if (! k_diffs(sin_beta, vd, delta_k_before, delta_k_behind))
+ {
+ return false;
+ }
+
+ CT const t_t0j = t / t0j;
+ // NOTE: t may be slightly out of bounds here
+ CT const asin_t_t0j = asin(bounded(t_t0j, -c1, c1));
+ CT const sign_asin_t_t0j = sign_lon_diff * asin_t_t0j;
+ delta_lon_before = sign_asin_t_t0j + delta_k_before;
+ delta_lon_behind = -sign_asin_t_t0j + delta_k_behind;
+
+ return true;
+ }
+
+ bool lon(CT const& sin_beta, CT const& t, vertex_data const& vd,
+ CT & lon_before, CT & lon_behind) const
+ {
+ using math::detail::bounded;
+ CT const c1 = 1;
+ CT const pi = math::pi<CT>();
+
+ if (is_Cj_zero)
+ {
+ lon_before = lonj;
+ lon_behind = lonj + sign_lon_diff * pi;
+ return true;
+ }
+
+ if (! (is_sin_beta_ok(sin_beta)
+ || math::equals(math::abs(sin_beta), sqrt_1_Cj_sqr)) )
+ {
+ return false;
+ }
+
+ CT const t_t0j = t / t0j;
+ CT const asin_t_t0j = asin(bounded(t_t0j, -c1, c1));
+ CT const dLj = d_lambda(sin_beta);
+ lon_before = lonj + sign_lon_diff * (asin_t_t0j - asin_tj_t0j + dLj);
+ lon_behind = vd.lon0j + (vd.lon0j - lon_before);
+
+ return true;
+ }
+
+
+ CT lon(CT const& delta_lon) const
+ {
+ return lonj + delta_lon;
+ }
+
+ CT lat(CT const& t) const
+ {
+ // t = tan(beta) = (1-f)tan(lat)
+ return atan(t / one_minus_f);
+ }
+
+ void vertex(CT & lon, CT & lat) const
+ {
+ lon = get_vertex_data().lon0j;
+ if (! is_Cj_zero)
+ {
+ lat = sjoberg_geodesic::lat(t0j);
+ }
+ else
+ {
+ CT const c2 = 2;
+ lat = math::pi<CT>() / c2;
+ }
+ }
+
+ CT lon_of_equator_intersection() const
+ {
+ CT const c0 = 0;
+ CT const dLj = d_lambda(c0);
+ CT const asin_tj_t0j = asin(Cj * tan_betaj / sqrt_1_Cj_sqr);
+ return lonj - asin_tj_t0j + dLj;
+ }
+
+ CT d_lambda(CT const& sin_beta) const
+ {
+ return sjoberg_d_lambda_e_sqr<Order>(sin_betaj, sin_beta, Cj, sqrt_1_Cj_sqr, e_sqr);
+ }
+
+ // [Sjoberg12]
+ /*CT d_lambda(CT const& sin_beta1, CT const& sin_beta2) const
+ {
+ return sjoberg_d_lambda_e_sqr<Order>(sin_beta1, sin_beta2, Cj, sqrt_1_Cj_sqr, e_sqr);
+ }*/
+
+ CT lonj;
+ CT latj;
+ CT alphaj;
+
+ CT one_minus_f;
+ CT e_sqr;
+
+ CT tan_latj;
+ CT tan_betaj;
+ CT betaj;
+ CT sin_betaj;
+ CT cos_betaj;
+ CT sin_alphaj;
+ CT Cj;
+ CT Cj_sqr;
+ CT sqrt_1_Cj_sqr;
+
+ int sign_lon_diff;
+
+ bool is_on_equator;
+ bool is_Cj_zero;
+
+ CT t0j;
+ CT asin_tj_t0j;
+};
+
+
+/*!
\brief The intersection of two geodesics as proposed by Sjoberg.
-\author See
+\see See
- [Sjoberg02] Lars E. Sjoberg, Intersections on the sphere and ellipsoid, 2002
http://link.springer.com/article/10.1007/s00190-001-0230-9
- [Sjoberg07] Lars E. Sjoberg, Geodetic intersection on the ellipsoid, 2007
http://link.springer.com/article/10.1007/s00190-007-0204-7
+ - [Sjoberg12] Lars E. Sjoberg, Solutions to the ellipsoidal Clairaut constant
+ and the inverse geodetic problem by numerical integration, 2012
+ https://www.degruyter.com/view/j/jogs.2012.2.issue-3/v10156-011-0037-4/v10156-011-0037-4.xml
*/
template
<
@@ -42,9 +629,14 @@ template
>
class sjoberg_intersection
{
+ typedef sjoberg_geodesic<CT, Order> geodesic_type;
typedef Inverse<CT, false, true, false, false, false> inverse_type;
typedef typename inverse_type::result_type inverse_result;
+ static bool const enable_02 = true;
+ static int const max_iterations_02 = 10;
+ static int const max_iterations_07 = 20;
+
public:
template <typename T1, typename T2, typename Spheroid>
static inline bool apply(T1 const& lona1, T1 const& lata1,
@@ -63,320 +655,562 @@ public:
CT const lon_b2 = lonb2;
CT const lat_b2 = latb2;
- CT const alpha1 = inverse_type::apply(lon_a1, lat_a1, lon_a2, lat_a2, spheroid).azimuth;
- CT const alpha2 = inverse_type::apply(lon_b1, lat_b1, lon_b2, lat_b2, spheroid).azimuth;
+ inverse_result const res1 = inverse_type::apply(lon_a1, lat_a1, lon_a2, lat_a2, spheroid);
+ inverse_result const res2 = inverse_type::apply(lon_b1, lat_b1, lon_b2, lat_b2, spheroid);
- return apply(lon_a1, lat_a1, alpha1, lon_b1, lat_b1, alpha2, lon, lat, spheroid);
+ return apply(lon_a1, lat_a1, lon_a2, lat_a2, res1.azimuth,
+ lon_b1, lat_b1, lon_b2, lat_b2, res2.azimuth,
+ lon, lat, spheroid);
}
-
+
+ // TODO: Currently may not work correctly if one of the endpoints is the pole
template <typename Spheroid>
- static inline bool apply(CT const& lon1, CT const& lat1, CT const& alpha1,
- CT const& lon2, CT const& lat2, CT const& alpha2,
+ static inline bool apply(CT const& lon_a1, CT const& lat_a1, CT const& lon_a2, CT const& lat_a2, CT const& alpha_a1,
+ CT const& lon_b1, CT const& lat_b1, CT const& lon_b2, CT const& lat_b2, CT const& alpha_b1,
CT & lon, CT & lat,
Spheroid const& spheroid)
{
// coordinates in radians
- // TODO - handle special cases like degenerated segments, equator, poles, etc.
-
CT const c0 = 0;
CT const c1 = 1;
- CT const c2 = 2;
- CT const pi = math::pi<CT>();
- CT const pi_half = pi / c2;
- CT const f = detail::flattening<CT>(spheroid);
+ CT const f = formula::flattening<CT>(spheroid);
CT const one_minus_f = c1 - f;
- CT const e_sqr = f * (c2 - f);
-
- CT const sin_alpha1 = sin(alpha1);
- CT const sin_alpha2 = sin(alpha2);
-
- CT const tan_beta1 = one_minus_f * tan(lat1);
- CT const tan_beta2 = one_minus_f * tan(lat2);
- CT const beta1 = atan(tan_beta1);
- CT const beta2 = atan(tan_beta2);
- CT const cos_beta1 = cos(beta1);
- CT const cos_beta2 = cos(beta2);
- CT const sin_beta1 = sin(beta1);
- CT const sin_beta2 = sin(beta2);
-
- // Clairaut constants (lower-case in the paper)
- int const sign_C1 = math::abs(alpha1) <= pi_half ? 1 : -1;
- int const sign_C2 = math::abs(alpha2) <= pi_half ? 1 : -1;
- // Cj = 1 if on equator
- CT const C1 = sign_C1 * cos_beta1 * sin_alpha1;
- CT const C2 = sign_C2 * cos_beta2 * sin_alpha2;
-
- CT const sqrt_1_C1_sqr = math::sqrt(c1 - math::sqr(C1));
- CT const sqrt_1_C2_sqr = math::sqrt(c1 - math::sqr(C2));
-
- // handle special case: segments on the equator
- bool const on_equator1 = math::equals(sqrt_1_C1_sqr, c0);
- bool const on_equator2 = math::equals(sqrt_1_C2_sqr, c0);
- if (on_equator1 && on_equator2)
+
+ geodesic_type geod1(lon_a1, lat_a1, alpha_a1, f);
+ geodesic_type geod2(lon_b1, lat_b1, alpha_b1, f);
+
+ // Cj = 1 if on equator <=> sqrt_1_Cj_sqr = 0
+ // Cj = 0 if vertical <=> sqrt_1_Cj_sqr = 1
+
+ if (geod1.is_on_equator && geod2.is_on_equator)
{
return false;
}
- else if (on_equator1)
+ else if (geod1.is_on_equator)
{
- CT const dL2 = d_lambda_e_sqr(sin_beta2, c0, C2, sqrt_1_C2_sqr, e_sqr);
- CT const asin_t2_t02 = asin(C2 * tan_beta2 / sqrt_1_C2_sqr);
+ lon = geod2.lon_of_equator_intersection();
lat = c0;
- lon = lon2 - asin_t2_t02 + dL2;
return true;
}
- else if (on_equator2)
+ else if (geod2.is_on_equator)
{
- CT const dL1 = d_lambda_e_sqr(sin_beta1, c0, C1, sqrt_1_C1_sqr, e_sqr);
- CT const asin_t1_t01 = asin(C1 * tan_beta1 / sqrt_1_C1_sqr);
+ lon = geod1.lon_of_equator_intersection();
lat = c0;
- lon = lon1 - asin_t1_t01 + dL1;
return true;
}
- CT const t01 = sqrt_1_C1_sqr / C1;
- CT const t02 = sqrt_1_C2_sqr / C2;
+ // (lon1 - lon2) normalized to (-180, 180]
+ CT const lon1_minus_lon2 = math::longitude_distance_signed<radian>(geod2.lonj, geod1.lonj);
- CT const asin_t1_t01 = asin(tan_beta1 / t01);
- CT const asin_t2_t02 = asin(tan_beta2 / t02);
- CT const t01_t02 = t01 * t02;
- CT const t01_t02_2 = c2 * t01_t02;
- CT const sqr_t01_sqr_t02 = math::sqr(t01) + math::sqr(t02);
+ // vertical segments
+ if (geod1.is_Cj_zero && geod2.is_Cj_zero)
+ {
+ CT const pi = math::pi<CT>();
- CT t = tan_beta1;
- int t_id = 0;
+ // the geodesics are parallel, the intersection point cannot be calculated
+ if ( math::equals(lon1_minus_lon2, c0)
+ || math::equals(lon1_minus_lon2 + (lon1_minus_lon2 < c0 ? pi : -pi), c0) )
+ {
+ return false;
+ }
- // find the initial t using simplified spherical solution
- // though not entirely since the reduced latitudes and azimuths are spheroidal
- // [Sjoberg07]
- CT const k_base = lon1 - lon2 + asin_t2_t02 - asin_t1_t01;
-
+ lon = c0;
+
+ // the geodesics intersect at one of the poles
+ CT const pi_half = pi / CT(2);
+ CT const abs_lat_a1 = math::abs(lat_a1);
+ CT const abs_lat_a2 = math::abs(lat_a2);
+ if (math::equals(abs_lat_a1, abs_lat_a2))
+ {
+ lat = pi_half;
+ }
+ else
+ {
+ // pick the pole closest to one of the points of the first segment
+ CT const& closer_lat = abs_lat_a1 > abs_lat_a2 ? lat_a1 : lat_a2;
+ lat = closer_lat >= 0 ? pi_half : -pi_half;
+ }
+
+ return true;
+ }
+
+ CT lon_sph = 0;
+
+ // Starting tan(beta)
+ CT t = 0;
+
+ /*if (geod1.is_Cj_zero)
{
- CT const K = sin(k_base);
- CT const d1 = sqr_t01_sqr_t02;
- //CT const d2 = t01_t02_2 * math::sqrt(c1 - math::sqr(K));
- CT const d2 = t01_t02_2 * cos(k_base);
- CT const D1 = math::sqrt(d1 - d2);
- CT const D2 = math::sqrt(d1 + d2);
- CT const K_t01_t02 = K * t01_t02;
-
- CT const T1 = K_t01_t02 / D1;
- CT const T2 = K_t01_t02 / D2;
- CT asin_T1_t01 = 0;
- CT asin_T1_t02 = 0;
- CT asin_T2_t01 = 0;
- CT asin_T2_t02 = 0;
-
- // test 4 possible results
- CT l1 = 0, l2 = 0, dl = 0;
- bool found = check_t<0>( T1,
- lon1, asin_T1_t01 = asin(T1 / t01), asin_t1_t01,
- lon2, asin_T1_t02 = asin(T1 / t02), asin_t2_t02,
- t, l1, l2, dl, t_id)
- || check_t<1>(-T1,
- lon1, -asin_T1_t01 , asin_t1_t01,
- lon2, -asin_T1_t02 , asin_t2_t02,
- t, l1, l2, dl, t_id)
- || check_t<2>( T2,
- lon1, asin_T2_t01 = asin(T2 / t01), asin_t1_t01,
- lon2, asin_T2_t02 = asin(T2 / t02), asin_t2_t02,
- t, l1, l2, dl, t_id)
- || check_t<3>(-T2,
- lon1, -asin_T2_t01 , asin_t1_t01,
- lon2, -asin_T2_t02 , asin_t2_t02,
- t, l1, l2, dl, t_id);
-
- boost::ignore_unused(found);
+ CT const k_base = lon1_minus_lon2 + geod2.sign_lon_diff * geod2.asin_tj_t0j;
+ t = sin(k_base) * geod2.t0j;
+ lon_sph = vertical_intersection_longitude(geod1.lonj, lon_b1, lon_b2);
}
+ else if (geod2.is_Cj_zero)
+ {
+ CT const k_base = lon1_minus_lon2 - geod1.sign_lon_diff * geod1.asin_tj_t0j;
+ t = sin(-k_base) * geod1.t0j;
+ lon_sph = vertical_intersection_longitude(geod2.lonj, lon_a1, lon_a2);
+ }
+ else*/
+ {
+ // TODO: Consider using betas instead of latitudes.
+ // Some function calls might be saved this way.
+ CT tan_lat_sph = 0;
+ sjoberg_intersection_spherical_02<CT>::apply_alt(lon_a1, lat_a1, lon_a2, lat_a2,
+ lon_b1, lat_b1, lon_b2, lat_b2,
+ lon_sph, tan_lat_sph);
+ t = one_minus_f * tan_lat_sph; // tan(beta)
+ }
+
+ // TODO: no need to calculate atan here if reduced latitudes were used
+ // instead of latitudes above, in sjoberg_intersection_spherical_02
+ CT const beta = atan(t);
+
+ if (enable_02 && newton_method(geod1, geod2, beta, t, lon1_minus_lon2, lon, lat))
+ {
+ return true;
+ }
+
+ return converge_07(geod1, geod2, beta, t, lon1_minus_lon2, lon_sph, lon, lat);
+ }
+
+private:
+ static inline bool newton_method(geodesic_type const& geod1, geodesic_type const& geod2, // in
+ CT beta, CT t, CT const& lon1_minus_lon2, // in
+ CT & lon, CT & lat) // out
+ {
+ CT const c0 = 0;
+ CT const c1 = 1;
+
+ CT const e_sqr = geod1.e_sqr;
- // [Sjoberg07]
- //int const d2_sign = t_id < 2 ? -1 : 1;
- int const t_sign = (t_id % 2) ? -1 : 1;
- // [Sjoberg02]
- CT const C1_sqr = math::sqr(C1);
- CT const C2_sqr = math::sqr(C2);
-
- CT beta = atan(t);
- CT dL1 = 0, dL2 = 0;
- CT asin_t_t01 = 0;
- CT asin_t_t02 = 0;
+ CT lon1_diff = 0;
+ CT lon2_diff = 0;
- for (int i = 0; i < 10; ++i)
+ CT abs_dbeta_last = 0;
+
+ // [Sjoberg02] converges faster than solution in [Sjoberg07]
+ // Newton-Raphson method
+ for (int i = 0; i < max_iterations_02; ++i)
{
CT const sin_beta = sin(beta);
-
- // integrals approximation
- dL1 = d_lambda_e_sqr(sin_beta1, sin_beta, C1, sqrt_1_C1_sqr, e_sqr);
- dL2 = d_lambda_e_sqr(sin_beta2, sin_beta, C2, sqrt_1_C2_sqr, e_sqr);
-
- // [Sjoberg07]
- /*CT const k = k_base + dL1 - dL2;
- CT const K = sin(k);
- CT const d1 = sqr_t01_sqr_t02;
- //CT const d2 = t01_t02_2 * math::sqrt(c1 - math::sqr(K));
- CT const d2 = t01_t02_2 * cos(k);
- CT const D = math::sqrt(d1 + d2_sign * d2);
- CT const t_new = t_sign * K * t01_t02 / D;
- CT const dt = math::abs(t_new - t);
- t = t_new;
- CT const new_beta = atan(t);
- CT const dbeta = math::abs(new_beta - beta);
- beta = new_beta;*/
-
- // [Sjoberg02] - it converges faster
- // Newton–Raphson method
- asin_t_t01 = asin(t / t01);
- asin_t_t02 = asin(t / t02);
- CT const R1 = asin_t_t01 + dL1;
- CT const R2 = asin_t_t02 + dL2;
CT const cos_beta = cos(beta);
CT const cos_beta_sqr = math::sqr(cos_beta);
CT const G = c1 - e_sqr * cos_beta_sqr;
- CT const f1 = C1 / cos_beta * math::sqrt(G / (cos_beta_sqr - C1_sqr));
- CT const f2 = C2 / cos_beta * math::sqrt(G / (cos_beta_sqr - C2_sqr));
- CT const abs_f1 = math::abs(f1);
- CT const abs_f2 = math::abs(f2);
- CT const dbeta = t_sign * (k_base - R2 + R1) / (abs_f1 + abs_f2);
-
- if (math::equals(dbeta, CT(0)))
+
+ CT f1 = 0;
+ CT f2 = 0;
+
+ if (!geod1.is_Cj_zero)
+ {
+ bool is_beta_ok = geod1.lon_diff(sin_beta, t, lon1_diff);
+
+ if (is_beta_ok)
+ {
+ CT const H = cos_beta_sqr - geod1.Cj_sqr;
+ f1 = geod1.Cj / cos_beta * math::sqrt(G / H);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (!geod2.is_Cj_zero)
+ {
+ bool is_beta_ok = geod2.lon_diff(sin_beta, t, lon2_diff);
+
+ if (is_beta_ok)
+ {
+ CT const H = cos_beta_sqr - geod2.Cj_sqr;
+ f2 = geod2.Cj / cos_beta * math::sqrt(G / H);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // NOTE: Things may go wrong if the IP is near the vertex
+ // 1. May converge into the wrong direction (from the other way around).
+ // This happens when the starting point is on the other side than the vertex
+ // 2. During converging may "jump" into the other side of the vertex.
+ // In this case sin_beta/sqrt_1_Cj_sqr and t/t0j is not in [-1, 1]
+ // 3. f1-f2 may be 0 which means that the intermediate point is on the vertex
+ // In this case it's not possible to check if this is the correct result
+
+ CT const dbeta_denom = f1 - f2;
+ //CT const dbeta_denom = math::abs(f1) + math::abs(f2);
+
+ if (math::equals(dbeta_denom, c0))
+ {
+ return false;
+ }
+
+ // The sign of dbeta is changed WRT [Sjoberg02]
+ CT const dbeta = (lon1_minus_lon2 + lon1_diff - lon2_diff) / dbeta_denom;
+
+ CT const abs_dbeta = math::abs(dbeta);
+ if (i > 0 && abs_dbeta > abs_dbeta_last)
{
+ // The algorithm is not converging
+ // The intersection may be on the other side of the vertex
+ return false;
+ }
+ abs_dbeta_last = abs_dbeta;
+
+ if (math::equals(dbeta, c0))
+ {
+ // Result found
break;
}
+ // Because the sign of dbeta is changed WRT [Sjoberg02] dbeta is subtracted here
beta = beta - dbeta;
+
t = tan(beta);
}
-
- // t = tan(beta) = (1-f)tan(lat)
- lat = atan(t / one_minus_f);
- CT const l1 = lon1 + asin_t_t01 - asin_t1_t01 + dL1;
- //CT const l2 = lon2 + asin_t_t02 - asin_t2_t02 + dL2;
- lon = l1;
+ lat = geod1.lat(t);
+ // NOTE: if Cj is 0 then the result is lonj or lonj+180
+ lon = ! geod1.is_Cj_zero
+ ? geod1.lon(lon1_diff)
+ : geod2.lon(lon2_diff);
return true;
}
-private:
- /*! Approximation of dLambda_j [Sjoberg07], expanded into taylor series in e^2
- Maxima script:
- dLI_j(c_j, sinB_j, sinB) := integrate(1 / (sqrt(1 - c_j ^ 2 - x ^ 2)*(1 + sqrt(1 - e2*(1 - x ^ 2)))), x, sinB_j, sinB);
- dL_j(c_j, B_j, B) := -e2 * c_j * dLI_j(c_j, B_j, B);
- S: taylor(dLI_j(c_j, sinB_j, sinB), e2, 0, 3);
- assume(c_j < 1);
- assume(c_j > 0);
- L1: factor(integrate(sqrt(-x ^ 2 - c_j ^ 2 + 1) / (x ^ 2 + c_j ^ 2 - 1), x));
- L2: factor(integrate(((x ^ 2 - 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
- L3: factor(integrate(((x ^ 4 - 2 * x ^ 2 + 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
- L4: factor(integrate(((x ^ 6 - 3 * x ^ 4 + 3 * x ^ 2 - 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
- */
- static inline CT d_lambda_e_sqr(CT const& sin_betaj, CT const& sin_beta,
- CT const& Cj, CT const& sqrt_1_Cj_sqr,
- CT const& e_sqr)
- {
- if (Order == 0)
- {
- return 0;
- }
+ struct geodesics_type
+ {
+ geodesics_type(geodesic_type const& g1, geodesic_type const& g2)
+ : geod1(g1)
+ , geod2(g2)
+ , vertex1(geod1.get_vertex_data())
+ , vertex2(geod2.get_vertex_data())
+ {}
- CT const c2 = 2;
-
- CT const asin_B = asin(sin_beta / sqrt_1_Cj_sqr);
- CT const asin_Bj = asin(sin_betaj / sqrt_1_Cj_sqr);
- CT const L0 = (asin_B - asin_Bj) / c2;
+ geodesic_type const& geod1;
+ geodesic_type const& geod2;
+ typename geodesic_type::vertex_data vertex1;
+ typename geodesic_type::vertex_data vertex2;
+ };
- if (Order == 1)
+ struct converge_07_result
+ {
+ converge_07_result()
+ : lon1(0), lon2(0), k1_diff(0), k2_diff(0), t1(0), t2(0)
+ {}
+
+ CT lon1, lon2;
+ CT k1_diff, k2_diff;
+ CT t1, t2;
+ };
+
+ static inline bool converge_07(geodesic_type const& geod1, geodesic_type const& geod2,
+ CT beta, CT t,
+ CT const& lon1_minus_lon2, CT const& lon_sph,
+ CT & lon, CT & lat)
+ {
+ //CT const c0 = 0;
+ //CT const c1 = 1;
+ //CT const c2 = 2;
+ //CT const pi = math::pi<CT>();
+
+ geodesics_type geodesics(geod1, geod2);
+ converge_07_result result;
+
+ // calculate first pair of longitudes
+ if (!converge_07_step_one(CT(sin(beta)), t, lon1_minus_lon2, geodesics, lon_sph, result, false))
{
- return -Cj * e_sqr * L0;
+ return false;
}
- CT const c1 = 1;
- CT const c16 = 16;
+ int t_direction = 0;
- CT const X = sin_beta;
- CT const Xj = sin_betaj;
- CT const Cj_sqr = math::sqr(Cj);
- CT const Cj_sqr_plus_one = Cj_sqr + c1;
- CT const one_minus_Cj_sqr = c1 - Cj_sqr;
- CT const sqrt_Y = math::sqrt(-math::sqr(X) + one_minus_Cj_sqr);
- CT const sqrt_Yj = math::sqrt(-math::sqr(Xj) + one_minus_Cj_sqr);
- CT const L1 = (Cj_sqr_plus_one * (asin_B - asin_Bj) + X * sqrt_Y - Xj * sqrt_Yj) / c16;
+ CT lon_diff_prev = math::longitude_difference<radian>(result.lon1, result.lon2);
- if (Order == 2)
+ // [Sjoberg07]
+ for (int i = 2; i < max_iterations_07; ++i)
{
- return -Cj * e_sqr * (L0 + e_sqr * L1);
+ // pick t candidates from previous result based on dir
+ CT t_cand1 = result.t1;
+ CT t_cand2 = result.t2;
+ // if direction is 0 the closer one is the first
+ if (t_direction < 0)
+ {
+ t_cand1 = (std::min)(result.t1, result.t2);
+ t_cand2 = (std::max)(result.t1, result.t2);
+ }
+ else if (t_direction > 0)
+ {
+ t_cand1 = (std::max)(result.t1, result.t2);
+ t_cand2 = (std::min)(result.t1, result.t2);
+ }
+ else
+ {
+ t_direction = t_cand1 < t_cand2 ? -1 : 1;
+ }
+
+ CT t1 = t;
+ CT beta1 = beta;
+ // check if the further calculation is needed
+ if (converge_07_update(t1, beta1, t_cand1))
+ {
+ break;
+ }
+
+ bool try_t2 = false;
+ converge_07_result result_curr;
+ if (converge_07_step_one(CT(sin(beta1)), t1, lon1_minus_lon2, geodesics, lon_sph, result_curr))
+ {
+ CT const lon_diff1 = math::longitude_difference<radian>(result_curr.lon1, result_curr.lon2);
+ if (lon_diff_prev > lon_diff1)
+ {
+ t = t1;
+ beta = beta1;
+ lon_diff_prev = lon_diff1;
+ result = result_curr;
+ }
+ else if (t_cand1 != t_cand2)
+ {
+ try_t2 = true;
+ }
+ else
+ {
+ // the result is not fully correct but it won't be more accurate
+ break;
+ }
+ }
+ // ! converge_07_step_one
+ else
+ {
+ if (t_cand1 != t_cand2)
+ {
+ try_t2 = true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+ if (try_t2)
+ {
+ CT t2 = t;
+ CT beta2 = beta;
+ // check if the further calculation is needed
+ if (converge_07_update(t2, beta2, t_cand2))
+ {
+ break;
+ }
+
+ if (! converge_07_step_one(CT(sin(beta2)), t2, lon1_minus_lon2, geodesics, lon_sph, result_curr))
+ {
+ return false;
+ }
+
+ CT const lon_diff2 = math::longitude_difference<radian>(result_curr.lon1, result_curr.lon2);
+ if (lon_diff_prev > lon_diff2)
+ {
+ t_direction *= -1;
+ t = t2;
+ beta = beta2;
+ lon_diff_prev = lon_diff2;
+ result = result_curr;
+ }
+ else
+ {
+ // the result is not fully correct but it won't be more accurate
+ break;
+ }
+ }
}
- CT const c3 = 3;
- CT const c5 = 5;
- CT const c128 = 128;
+ lat = geod1.lat(t);
+ lon = ! geod1.is_Cj_zero ? result.lon1 : result.lon2;
+ math::normalize_longitude<radian>(lon);
+
+ return true;
+ }
+
+ static inline bool converge_07_update(CT & t, CT & beta, CT const& t_new)
+ {
+ CT const c0 = 0;
+
+ CT const beta_new = atan(t_new);
+ CT const dbeta = beta_new - beta;
+ beta = beta_new;
+ t = t_new;
- CT const E = Cj_sqr * (c3 * Cj_sqr + c2) + c3;
- CT const X_sqr = math::sqr(X);
- CT const Xj_sqr = math::sqr(Xj);
- CT const F = X * (-c2 * X_sqr + c3 * Cj_sqr + c5);
- CT const Fj = Xj * (-c2 * Xj_sqr + c3 * Cj_sqr + c5);
- CT const L2 = (E * (asin_B - asin_Bj) + F * sqrt_Y - Fj * sqrt_Yj) / c128;
+ return math::equals(dbeta, c0);
+ }
- if (Order == 3)
+ static inline CT const& pick_t(CT const& t1, CT const& t2, int direction)
+ {
+ return direction < 0 ? (std::min)(t1, t2) : (std::max)(t1, t2);
+ }
+
+ static inline bool converge_07_step_one(CT const& sin_beta,
+ CT const& t,
+ CT const& lon1_minus_lon2,
+ geodesics_type const& geodesics,
+ CT const& lon_sph,
+ converge_07_result & result,
+ bool check_sin_beta = true)
+ {
+ bool ok = converge_07_one_geod(sin_beta, t, geodesics.geod1, geodesics.vertex1, lon_sph,
+ result.lon1, result.k1_diff, check_sin_beta)
+ && converge_07_one_geod(sin_beta, t, geodesics.geod2, geodesics.vertex2, lon_sph,
+ result.lon2, result.k2_diff, check_sin_beta);
+
+ if (!ok)
{
- return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * L2));
+ return false;
}
- CT const c8 = 8;
- CT const c9 = 9;
- CT const c10 = 10;
- CT const c15 = 15;
- CT const c24 = 24;
- CT const c26 = 26;
- CT const c33 = 33;
- CT const c6144 = 6144;
+ CT const k = lon1_minus_lon2 + result.k1_diff - result.k2_diff;
- CT const G = Cj_sqr * (Cj_sqr * (Cj_sqr * c15 + c9) + c9) + c15;
- CT const H = -c10 * Cj_sqr - c26;
- CT const I = Cj_sqr * (Cj_sqr * c15 + c24) + c33;
- CT const J = X_sqr * (X * (c8 * X_sqr + H)) + X * I;
- CT const Jj = Xj_sqr * (Xj * (c8 * Xj_sqr + H)) + Xj * I;
- CT const L3 = (G * (asin_B - asin_Bj) + J * sqrt_Y - Jj * sqrt_Yj) / c6144;
+ // get 2 possible ts one lesser and one greater than t
+ // t1 is the closer one
+ calc_ts(t, k, geodesics.geod1, geodesics.geod2, result.t1, result.t2);
- // Order 4 and higher
- return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * (L2 + e_sqr * L3)));
+ return true;
}
- static inline CT fj(CT const& cos_beta, CT const& cos2_beta, CT const& Cj, CT const& e_sqr)
+ static inline bool converge_07_one_geod(CT const& sin_beta, CT const& t,
+ geodesic_type const& geod,
+ typename geodesic_type::vertex_data const& vertex,
+ CT const& lon_sph,
+ CT & lon, CT & k_diff,
+ bool check_sin_beta)
{
+ using math::detail::bounded;
CT const c1 = 1;
- CT const Cj_sqr = math::sqr(Cj);
- return Cj / cos_beta * math::sqrt((c1 - e_sqr * cos2_beta) / (cos2_beta - Cj_sqr));
+
+ CT k_diff_before = 0;
+ CT k_diff_behind = 0;
+
+ bool is_beta_ok = geod.k_diffs(sin_beta, vertex, k_diff_before, k_diff_behind, check_sin_beta);
+
+ if (! is_beta_ok)
+ {
+ return false;
+ }
+
+ CT const asin_t_t0j = ! geod.is_Cj_zero ? asin(bounded(t / geod.t0j, -c1, c1)) : 0;
+ CT const sign_asin_t_t0j = geod.sign_lon_diff * asin_t_t0j;
+
+ CT const lon_before = geod.lonj + sign_asin_t_t0j + k_diff_before;
+ CT const lon_behind = geod.lonj - sign_asin_t_t0j + k_diff_behind;
+
+ CT const lon_dist_before = math::longitude_distance_signed<radian>(lon_before, lon_sph);
+ CT const lon_dist_behind = math::longitude_distance_signed<radian>(lon_behind, lon_sph);
+ if (math::abs(lon_dist_before) <= math::abs(lon_dist_behind))
+ {
+ k_diff = k_diff_before;
+ lon = lon_before;
+ }
+ else
+ {
+ k_diff = k_diff_behind;
+ lon = lon_behind;
+ }
+
+ return true;
}
- template <int TId>
- static inline bool check_t(CT const& t,
- CT const& lon_a1, CT const& asin_t_t01, CT const& asin_t1_t01,
- CT const& lon_b1, CT const& asin_t_t02, CT const& asin_t2_t02,
- CT & current_t, CT & current_lon1, CT & current_lon2, CT & current_dlon,
- int & t_id)
+ static inline void calc_ts(CT const& t, CT const& k,
+ geodesic_type const& geod1, geodesic_type const& geod2,
+ CT & t1, CT& t2)
{
- CT const lon1 = lon_a1 + asin_t_t01 - asin_t1_t01;
- CT const lon2 = lon_b1 + asin_t_t02 - asin_t2_t02;
+ CT const c1 = 1;
+ CT const c2 = 2;
- // TODO - true angle difference
- CT const dlon = math::abs(lon2 - lon1);
+ CT const K = sin(k);
- bool are_equal = math::equals(dlon, CT(0));
-
- if ((TId == 0) || are_equal || dlon < current_dlon)
+ BOOST_GEOMETRY_ASSERT(!geod1.is_Cj_zero || !geod2.is_Cj_zero);
+ if (geod1.is_Cj_zero)
+ {
+ t1 = K * geod2.t0j;
+ t2 = -t1;
+ }
+ else if (geod2.is_Cj_zero)
{
- current_t = t;
- current_lon1 = lon1;
- current_lon2 = lon2;
- current_dlon = dlon;
- t_id = TId;
+ t1 = -K * geod1.t0j;
+ t2 = -t1;
}
+ else
+ {
+ CT const A = math::sqr(geod1.t0j) + math::sqr(geod2.t0j);
+ CT const B = c2 * geod1.t0j * geod2.t0j * math::sqrt(c1 - math::sqr(K));
+
+ CT const K_t01_t02 = K * geod1.t0j * geod2.t0j;
+ CT const D1 = math::sqrt(A + B);
+ CT const D2 = math::sqrt(A - B);
+ CT const t_new1 = K_t01_t02 / D1;
+ CT const t_new2 = K_t01_t02 / D2;
+ CT const t_new3 = -t_new1;
+ CT const t_new4 = -t_new2;
- return are_equal;
+ // Pick 2 nearest t_new, one greater and one lesser than current t
+ CT const abs_t_new1 = math::abs(t_new1);
+ CT const abs_t_new2 = math::abs(t_new2);
+ CT const abs_t_max = (std::max)(abs_t_new1, abs_t_new2);
+ t1 = -abs_t_max; // lesser
+ t2 = abs_t_max; // greater
+ if (t1 < t)
+ {
+ if (t_new1 < t && t_new1 > t1)
+ t1 = t_new1;
+ if (t_new2 < t && t_new2 > t1)
+ t1 = t_new2;
+ if (t_new3 < t && t_new3 > t1)
+ t1 = t_new3;
+ if (t_new4 < t && t_new4 > t1)
+ t1 = t_new4;
+ }
+ if (t2 > t)
+ {
+ if (t_new1 > t && t_new1 < t2)
+ t2 = t_new1;
+ if (t_new2 > t && t_new2 < t2)
+ t2 = t_new2;
+ if (t_new3 > t && t_new3 < t2)
+ t2 = t_new3;
+ if (t_new4 > t && t_new4 < t2)
+ t2 = t_new4;
+ }
+ }
+
+ // the first one is the closer one
+ if (math::abs(t - t2) < math::abs(t - t1))
+ {
+ std::swap(t2, t1);
+ }
+ }
+
+ static inline CT fj(CT const& cos_beta, CT const& cos2_beta, CT const& Cj, CT const& e_sqr)
+ {
+ CT const c1 = 1;
+ CT const Cj_sqr = math::sqr(Cj);
+ return Cj / cos_beta * math::sqrt((c1 - e_sqr * cos2_beta) / (cos2_beta - Cj_sqr));
}
+
+ /*static inline CT vertical_intersection_longitude(CT const& ip_lon, CT const& seg_lon1, CT const& seg_lon2)
+ {
+ CT const c0 = 0;
+ CT const lon_2 = ip_lon > c0 ? ip_lon - pi : ip_lon + pi;
+
+ return (std::min)(math::longitude_difference<radian>(ip_lon, seg_lon1),
+ math::longitude_difference<radian>(ip_lon, seg_lon2))
+ <=
+ (std::min)(math::longitude_difference<radian>(lon_2, seg_lon1),
+ math::longitude_difference<radian>(lon_2, seg_lon2))
+ ? ip_lon : lon_2;
+ }*/
};
}}} // namespace boost::geometry::formula
diff --git a/boost/geometry/formulas/spherical.hpp b/boost/geometry/formulas/spherical.hpp
index 2195bbbe10..ff24c51a88 100644
--- a/boost/geometry/formulas/spherical.hpp
+++ b/boost/geometry/formulas/spherical.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry
// Copyright (c) 2016, 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,
@@ -27,38 +28,67 @@ namespace boost { namespace geometry {
namespace formula {
+template <typename T>
+struct result_spherical
+{
+ result_spherical()
+ : azimuth(0)
+ , reverse_azimuth(0)
+ {}
+
+ T azimuth;
+ T reverse_azimuth;
+};
+
+template <typename T>
+static inline void sph_to_cart3d(T const& lon, T const& lat, T & x, T & y, T & z)
+{
+ T const cos_lat = cos(lat);
+ x = cos_lat * cos(lon);
+ y = cos_lat * sin(lon);
+ z = sin(lat);
+}
+
template <typename Point3d, typename PointSph>
static inline Point3d sph_to_cart3d(PointSph const& point_sph)
{
typedef typename coordinate_type<Point3d>::type calc_t;
- Point3d res;
-
- calc_t lon = get_as_radian<0>(point_sph);
- calc_t lat = get_as_radian<1>(point_sph);
+ calc_t const lon = get_as_radian<0>(point_sph);
+ calc_t const lat = get_as_radian<1>(point_sph);
+ calc_t x, y, z;
+ sph_to_cart3d(lon, lat, x, y, z);
- calc_t const cos_lat = cos(lat);
- set<0>(res, cos_lat * cos(lon));
- set<1>(res, cos_lat * sin(lon));
- set<2>(res, sin(lat));
+ Point3d res;
+ set<0>(res, x);
+ set<1>(res, y);
+ set<2>(res, z);
return res;
}
+template <typename T>
+static inline void cart3d_to_sph(T const& x, T const& y, T const& z, T & lon, T & lat)
+{
+ lon = atan2(y, x);
+ lat = asin(z);
+}
+
template <typename PointSph, typename Point3d>
static inline PointSph cart3d_to_sph(Point3d const& point_3d)
{
typedef typename coordinate_type<PointSph>::type coord_t;
typedef typename coordinate_type<Point3d>::type calc_t;
- PointSph res;
-
calc_t const x = get<0>(point_3d);
calc_t const y = get<1>(point_3d);
calc_t const z = get<2>(point_3d);
+ calc_t lonr, latr;
+ cart3d_to_sph(x, y, z, lonr, latr);
- set_from_radian<0>(res, atan2(y, x));
- set_from_radian<1>(res, asin(z));
+ PointSph res;
+ set_from_radian<0>(res, lonr);
+ set_from_radian<1>(res, latr);
coord_t lon = get<0>(res);
coord_t lat = get<1>(res);
@@ -89,6 +119,104 @@ static inline int sph_side_value(Point3d1 const& norm, Point3d2 const& pt)
: -1; // d < 0
}
+template <typename CT, bool ReverseAzimuth, typename T1, typename T2>
+static inline result_spherical<CT> spherical_azimuth(T1 const& lon1,
+ T1 const& lat1,
+ T2 const& lon2,
+ T2 const& lat2)
+{
+ typedef result_spherical<CT> result_type;
+ result_type result;
+
+ // http://williams.best.vwh.net/avform.htm#Crs
+ // https://en.wikipedia.org/wiki/Great-circle_navigation
+ CT dlon = lon2 - lon1;
+
+ // An optimization which should kick in often for Boxes
+ //if ( math::equals(dlon, ReturnType(0)) )
+ //if ( get<0>(p1) == get<0>(p2) )
+ //{
+ // return - sin(get_as_radian<1>(p1)) * cos_p2lat);
+ //}
+
+ CT const cos_dlon = cos(dlon);
+ CT const sin_dlon = sin(dlon);
+ CT const cos_lat1 = cos(lat1);
+ CT const cos_lat2 = cos(lat2);
+ CT const sin_lat1 = sin(lat1);
+ CT const sin_lat2 = sin(lat2);
+
+ {
+ // "An alternative formula, not requiring the pre-computation of d"
+ // In the formula below dlon is used as "d"
+ CT const y = sin_dlon * cos_lat2;
+ CT const x = cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon;
+ result.azimuth = atan2(y, x);
+ }
+
+ if (ReverseAzimuth)
+ {
+ CT const y = sin_dlon * cos_lat1;
+ CT const x = sin_lat2 * cos_lat1 * cos_dlon - cos_lat2 * sin_lat1;
+ result.reverse_azimuth = atan2(y, x);
+ }
+
+ return result;
+}
+
+template <typename ReturnType, typename T1, typename T2>
+inline ReturnType spherical_azimuth(T1 const& lon1, T1 const& lat1,
+ T2 const& lon2, T2 const& lat2)
+{
+ return spherical_azimuth<ReturnType, false>(lon1, lat1, lon2, lat2).azimuth;
+}
+
+template <typename T>
+inline T spherical_azimuth(T const& lon1, T const& lat1, T const& lon2, T const& lat2)
+{
+ return spherical_azimuth<T, false>(lon1, lat1, lon2, lat2).azimuth;
+}
+
+template <typename T>
+inline int azimuth_side_value(T const& azi_a1_p, T const& azi_a1_a2)
+{
+ T const pi = math::pi<T>();
+ T const two_pi = math::two_pi<T>();
+
+ // instead of the formula from XTD
+ //calc_t a_diff = asin(sin(azi_a1_p - azi_a1_a2));
+
+ T a_diff = azi_a1_p - azi_a1_a2;
+ // normalize, angle in [-pi, pi]
+ while (a_diff > pi)
+ a_diff -= two_pi;
+ while (a_diff < -pi)
+ a_diff += two_pi;
+
+ // NOTE: in general it shouldn't be required to support the pi/-pi case
+ // because in non-cartesian systems it makes sense to check the side
+ // only "between" the endpoints.
+ // However currently the winding strategy calls the side strategy
+ // for vertical segments to check if the point is "between the endpoints.
+ // This could be avoided since the side strategy is not required for that
+ // because meridian is the shortest path. So a difference of
+ // longitudes would be sufficient (of course normalized to [-pi, pi]).
+
+ // NOTE: with the above said, the pi/-pi check is temporary
+ // however in case if this was required
+ // the geodesics on ellipsoid aren't "symmetrical"
+ // therefore instead of comparing a_diff to pi and -pi
+ // one should probably use inverse azimuths and compare
+ // the difference to 0 as well
+
+ // positive azimuth is on the right side
+ return math::equals(a_diff, 0)
+ || math::equals(a_diff, pi)
+ || math::equals(a_diff, -pi) ? 0
+ : a_diff > 0 ? -1 // right
+ : 1; // left
+}
+
} // namespace formula
}} // namespace boost::geometry
diff --git a/boost/geometry/formulas/thomas_direct.hpp b/boost/geometry/formulas/thomas_direct.hpp
index f8a7f83943..f208167cf5 100644
--- a/boost/geometry/formulas/thomas_direct.hpp
+++ b/boost/geometry/formulas/thomas_direct.hpp
@@ -20,9 +20,8 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/result_direct.hpp>
@@ -82,7 +81,7 @@ public:
CT const a = CT(get_radius<0>(spheroid));
CT const b = CT(get_radius<2>(spheroid));
- CT const f = detail::flattening<CT>(spheroid);
+ CT const f = formula::flattening<CT>(spheroid);
CT const one_minus_f = c1 - f;
CT const pi = math::pi<CT>();
diff --git a/boost/geometry/formulas/thomas_inverse.hpp b/boost/geometry/formulas/thomas_inverse.hpp
index d68c9de054..0853a36980 100644
--- a/boost/geometry/formulas/thomas_inverse.hpp
+++ b/boost/geometry/formulas/thomas_inverse.hpp
@@ -20,9 +20,8 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/result_inverse.hpp>
@@ -78,7 +77,7 @@ public:
CT const c4 = 4;
CT const pi_half = math::pi<CT>() / c2;
- CT const f = detail::flattening<CT>(spheroid);
+ CT const f = formula::flattening<CT>(spheroid);
CT const one_minus_f = c1 - f;
// CT const tan_theta1 = one_minus_f * tan(lat1);
diff --git a/boost/geometry/formulas/vertex_latitude.hpp b/boost/geometry/formulas/vertex_latitude.hpp
new file mode 100644
index 0000000000..755067b08d
--- /dev/null
+++ b/boost/geometry/formulas/vertex_latitude.hpp
@@ -0,0 +1,148 @@
+// 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_LATITUDE_HPP
+#define BOOST_GEOMETRY_FORMULAS_MAXIMUM_LATITUDE_HPP
+
+#include <boost/geometry/core/srs.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
+#include <boost/geometry/formulas/spherical.hpp>
+#include <boost/mpl/assert.hpp>
+
+namespace boost { namespace geometry { namespace formula
+{
+
+/*!
+\brief Algorithm to compute the vertex latitude of a geodesic segment. Vertex is
+a point on the geodesic that maximizes (or minimizes) the latitude.
+\author See
+ [Wood96] Wood - Vertex Latitudes on Ellipsoid Geodesics, SIAM Rev., 38(4),
+ 637–644, 1996
+*/
+
+template <typename CT>
+class vertex_latitude_on_sphere
+{
+
+public:
+ template<typename T1, typename T2>
+ static inline CT apply(T1 const& lat1,
+ T2 const& alp1)
+ {
+ return std::acos( math::abs(cos(lat1) * sin(alp1)) );
+ }
+};
+
+template <typename CT>
+class vertex_latitude_on_spheroid
+{
+
+public:
+/*
+ * formula based on paper
+ * [Wood96] Wood - Vertex Latitudes on Ellipsoid Geodesics, SIAM Rev., 38(4),
+ * 637–644, 1996
+ template <typename T1, typename T2, typename Spheroid>
+ static inline CT apply(T1 const& lat1,
+ T2 const& alp1,
+ Spheroid const& spheroid)
+ {
+ CT const f = formula::flattening<CT>(spheroid);
+
+ CT const e2 = f * (CT(2) - f);
+ CT const sin_alp1 = sin(alp1);
+ CT const sin2_lat1 = math::sqr(sin(lat1));
+ CT const cos2_lat1 = CT(1) - sin2_lat1;
+
+ CT const e2_sin2 = CT(1) - e2 * sin2_lat1;
+ CT const cos2_sin2 = cos2_lat1 * math::sqr(sin_alp1);
+ CT const vertex_lat = std::asin( math::sqrt((e2_sin2 - cos2_sin2)
+ / (e2_sin2 - e2 * cos2_sin2)));
+ return vertex_lat;
+ }
+*/
+
+ // simpler formula based on Clairaut relation for spheroids
+ template <typename T1, typename T2, typename Spheroid>
+ static inline CT apply(T1 const& lat1,
+ T2 const& alp1,
+ Spheroid const& spheroid)
+ {
+ CT const f = formula::flattening<CT>(spheroid);
+
+ CT const one_minus_f = (CT(1) - f);
+
+ //get the reduced latitude
+ CT const bet1 = atan( one_minus_f * tan(lat1) );
+
+ //apply Clairaut relation
+ CT const betv = vertex_latitude_on_sphere<CT>::apply(bet1, alp1);
+
+ //return the spheroid latitude
+ return atan( tan(betv) / one_minus_f );
+ }
+
+ /*
+ template <typename T>
+ inline static void sign_adjustment(CT lat1, CT lat2, CT vertex_lat, T& vrt_result)
+ {
+ // signbit returns a non-zero value (true) if the sign is negative;
+ // and zero (false) otherwise.
+ bool sign = std::signbit(std::abs(lat1) > std::abs(lat2) ? lat1 : lat2);
+
+ vrt_result.north = sign ? std::max(lat1, lat2) : vertex_lat;
+ vrt_result.south = sign ? vertex_lat * CT(-1) : std::min(lat1, lat2);
+ }
+
+ template <typename T>
+ inline static bool vertex_on_segment(CT alp1, CT alp2, CT lat1, CT lat2, T& vrt_result)
+ {
+ CT const half_pi = math::pi<CT>() / CT(2);
+
+ // if the segment does not contain the vertex of the geodesic
+ // then return the endpoint of max (min) latitude
+ if ((alp1 < half_pi && alp2 < half_pi)
+ || (alp1 > half_pi && alp2 > half_pi))
+ {
+ vrt_result.north = std::max(lat1, lat2);
+ vrt_result.south = std::min(lat1, lat2);
+ return false;
+ }
+ return true;
+ }
+ */
+};
+
+
+template <typename CT, typename CS_Tag>
+struct vertex_latitude
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM, (types<CS_Tag>)
+ );
+
+};
+
+template <typename CT>
+struct vertex_latitude<CT, spherical_equatorial_tag>
+ : vertex_latitude_on_sphere<CT>
+{};
+
+template <typename CT>
+struct vertex_latitude<CT, geographic_tag>
+ : vertex_latitude_on_spheroid<CT>
+{};
+
+
+}}} // namespace boost::geometry::formula
+
+#endif // BOOST_GEOMETRY_FORMULAS_MAXIMUM_LATITUDE_HPP
diff --git a/boost/geometry/formulas/vincenty_direct.hpp b/boost/geometry/formulas/vincenty_direct.hpp
index f3647ff4e6..1697e5fb63 100644
--- a/boost/geometry/formulas/vincenty_direct.hpp
+++ b/boost/geometry/formulas/vincenty_direct.hpp
@@ -23,9 +23,8 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/result_direct.hpp>
@@ -85,7 +84,7 @@ public:
CT const radius_a = CT(get_radius<0>(spheroid));
CT const radius_b = CT(get_radius<2>(spheroid));
- CT const flattening = geometry::detail::flattening<CT>(spheroid);
+ CT const flattening = formula::flattening<CT>(spheroid);
CT const sin_azimuth12 = sin(azimuth12);
CT const cos_azimuth12 = cos(azimuth12);
diff --git a/boost/geometry/formulas/vincenty_inverse.hpp b/boost/geometry/formulas/vincenty_inverse.hpp
index bbda00036b..032e16e291 100644
--- a/boost/geometry/formulas/vincenty_inverse.hpp
+++ b/boost/geometry/formulas/vincenty_inverse.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2016.
-// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -23,9 +23,8 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/result_inverse.hpp>
@@ -41,7 +40,7 @@ namespace boost { namespace geometry { namespace formula
\brief The solution of the inverse problem of geodesics on latlong coordinates, after Vincenty, 1975
\author See
- http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
- - http://www.icsm.gov.au/gda/gdav2.3.pdf
+ - http://www.icsm.gov.au/gda/gda-v_2.4.pdf
\author Adapted from various implementations to get it close to the original document
- http://www.movable-type.co.uk/scripts/LatLongVincenty.html
- http://exogen.case.edu/projects/geopy/source/geopy.distance.html
@@ -99,10 +98,10 @@ public:
CT const radius_a = CT(get_radius<0>(spheroid));
CT const radius_b = CT(get_radius<2>(spheroid));
- CT const flattening = geometry::detail::flattening<CT>(spheroid);
+ CT const f = formula::flattening<CT>(spheroid);
// U: reduced latitude, defined by tan U = (1-f) tan phi
- CT const one_min_f = c1 - flattening;
+ CT const one_min_f = c1 - f;
CT const tan_U1 = one_min_f * tan(lat1); // above (1)
CT const tan_U2 = one_min_f * tan(lat2); // above (1)
@@ -113,8 +112,9 @@ public:
CT const cos_U1 = c1 / temp_den_U1;
CT const cos_U2 = c1 / temp_den_U2;
// sin = tan / sqrt(1 + tan^2)
- CT const sin_U1 = tan_U1 / temp_den_U1;
- CT const sin_U2 = tan_U2 / temp_den_U2;
+ // sin = tan * cos
+ CT const sin_U1 = tan_U1 * cos_U1;
+ CT const sin_U2 = tan_U2 * cos_U2;
// calculate sin U and cos U directly
//CT const U1 = atan(tan_U1);
@@ -130,7 +130,8 @@ public:
CT sin_sigma;
CT sin_alpha;
CT cos2_alpha;
- CT cos2_sigma_m;
+ CT cos_2sigma_m;
+ CT cos2_2sigma_m;
CT sigma;
int counter = 0; // robustness
@@ -144,12 +145,13 @@ public:
CT cos_sigma = sin_U1 * sin_U2 + cos_U1 * cos_U2 * cos_lambda; // (15)
sin_alpha = cos_U1 * cos_U2 * sin_lambda / sin_sigma; // (17)
cos2_alpha = c1 - math::sqr(sin_alpha);
- cos2_sigma_m = math::equals(cos2_alpha, 0) ? 0 : cos_sigma - c2 * sin_U1 * sin_U2 / cos2_alpha; // (18)
+ cos_2sigma_m = math::equals(cos2_alpha, 0) ? 0 : cos_sigma - c2 * sin_U1 * sin_U2 / cos2_alpha; // (18)
+ cos2_2sigma_m = math::sqr(cos_2sigma_m);
- CT C = flattening/c16 * cos2_alpha * (c4 + flattening * (c4 - c3 * cos2_alpha)); // (10)
+ CT C = f/c16 * cos2_alpha * (c4 + f * (c4 - c3 * cos2_alpha)); // (10)
sigma = atan2(sin_sigma, cos_sigma); // (16)
- lambda = L + (c1 - C) * flattening * sin_alpha *
- (sigma + C * sin_sigma * ( cos2_sigma_m + C * cos_sigma * (-c1 + c2 * math::sqr(cos2_sigma_m)))); // (11)
+ lambda = L + (c1 - C) * f * sin_alpha *
+ (sigma + C * sin_sigma * (cos_2sigma_m + C * cos_sigma * (-c1 + c2 * cos2_2sigma_m))); // (11)
++counter; // robustness
@@ -182,8 +184,10 @@ public:
CT A = c1 + sqr_u/c16384 * (c4096 + sqr_u * (-c768 + sqr_u * (c320 - c175 * sqr_u))); // (3)
CT B = sqr_u/c1024 * (c256 + sqr_u * ( -c128 + sqr_u * (c74 - c47 * sqr_u))); // (4)
- CT delta_sigma = B * sin_sigma * ( cos2_sigma_m + (B/c4) * (cos(sigma)* (-c1 + c2 * cos2_sigma_m)
- - (B/c6) * cos2_sigma_m * (-c3 + c4 * math::sqr(sin_sigma)) * (-c3 + c4 * cos2_sigma_m))); // (6)
+ CT const cos_sigma = cos(sigma);
+ CT const sin2_sigma = math::sqr(sin_sigma);
+ CT delta_sigma = B * sin_sigma * (cos_2sigma_m + (B/c4) * (cos_sigma* (-c1 + c2 * cos2_2sigma_m)
+ - (B/c6) * cos_2sigma_m * (-c3 + c4 * sin2_sigma) * (-c3 + c4 * cos2_2sigma_m))); // (6)
result.distance = radius_b * A * (sigma - delta_sigma); // (19)
}
@@ -206,7 +210,7 @@ public:
typedef differential_quantities<CT, EnableReducedLength, EnableGeodesicScale, 2> quantities;
quantities::apply(lon1, lat1, lon2, lat2,
result.azimuth, result.reverse_azimuth,
- radius_b, flattening,
+ radius_b, f,
result.reduced_length, result.geodesic_scale);
}
diff --git a/boost/geometry/index/detail/algorithms/nth_element.hpp b/boost/geometry/index/detail/algorithms/nth_element.hpp
new file mode 100644
index 0000000000..201180ae3a
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/nth_element.hpp
@@ -0,0 +1,62 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 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
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_NTH_ELEMENT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_NTH_ELEMENT_HPP
+
+#include <algorithm>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+// See https://svn.boost.org/trac/boost/ticket/12861
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58800
+// https://gcc.gnu.org/develop.html#timeline
+// 20120920 4.7.2 - no bug
+// 20130322 4.8.0 - no bug
+// 20130411 4.7.3 - no bug
+// 20130531 4.8.1 - no bug
+// 20131016 4.8.2 - bug
+// 20140422 4.9.0 - fixed
+// 20140522 4.8.3 - fixed
+// 20140612 4.7.4 - fixed
+// 20140716 4.9.1 - fixed
+#if defined(__GLIBCXX__) && (__GLIBCXX__ == 20131016)
+
+#warning "std::nth_element replaced with std::sort, libstdc++ bug workaround.";
+
+template <typename RandomIt>
+void nth_element(RandomIt first, RandomIt , RandomIt last)
+{
+ std::sort(first, last);
+}
+
+template <typename RandomIt, typename Compare>
+void nth_element(RandomIt first, RandomIt , RandomIt last, Compare comp)
+{
+ std::sort(first, last, comp);
+}
+
+#else
+
+template <typename RandomIt>
+void nth_element(RandomIt first, RandomIt nth, RandomIt last)
+{
+ std::nth_element(first, nth, last);
+}
+
+template <typename RandomIt, typename Compare>
+void nth_element(RandomIt first, RandomIt nth, RandomIt last, Compare comp)
+{
+ std::nth_element(first, nth, last, comp);
+}
+
+#endif
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_NTH_ELEMENT_HPP
diff --git a/boost/geometry/index/detail/rtree/pack_create.hpp b/boost/geometry/index/detail/rtree/pack_create.hpp
index d1491b8d47..2d3903a7b4 100644
--- a/boost/geometry/index/detail/rtree/pack_create.hpp
+++ b/boost/geometry/index/detail/rtree/pack_create.hpp
@@ -2,7 +2,7 @@
//
// R-tree initial packing
//
-// 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,6 +13,7 @@
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/index/detail/algorithms/bounds.hpp>
+#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
@@ -67,7 +68,7 @@ struct nth_element_and_half_boxes
{
if ( I == dim_index )
{
- std::nth_element(first, median, last, point_entries_comparer<I>());
+ index::detail::nth_element(first, median, last, point_entries_comparer<I>());
geometry::convert(box, left);
geometry::convert(box, right);
diff --git a/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp b/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
index 7a96986a27..89697b5947 100644
--- a/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
+++ b/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
@@ -2,7 +2,7 @@
//
// R-tree R*-tree next node choosing algorithm implementation
//
-// 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
@@ -17,6 +17,7 @@
#include <boost/geometry/index/detail/algorithms/content.hpp>
#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>
+#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
#include <boost/geometry/index/detail/algorithms/union_content.hpp>
#include <boost/geometry/index/detail/rtree/node/node.hpp>
@@ -112,7 +113,7 @@ private:
first_n_children_count = overlap_cost_threshold;
// rearrange by content_diff
// in order to calculate nearly minimum overlap cost
- std::nth_element(children_contents.begin(), children_contents.begin() + first_n_children_count, children_contents.end(), content_diff_less);
+ index::detail::nth_element(children_contents.begin(), children_contents.begin() + first_n_children_count, children_contents.end(), content_diff_less);
}
// calculate minimum or nearly minimum overlap cost
diff --git a/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
index 8f270537fb..187d37facd 100644
--- a/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
+++ b/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
@@ -2,7 +2,7 @@
//
// R-tree R*-tree split algorithm implementation
//
-// 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
@@ -12,8 +12,9 @@
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>
-#include <boost/geometry/index/detail/algorithms/union_content.hpp>
#include <boost/geometry/index/detail/algorithms/margin.hpp>
+#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
+#include <boost/geometry/index/detail/algorithms/union_content.hpp>
#include <boost/geometry/index/detail/bounded_view.hpp>
@@ -122,8 +123,9 @@ struct choose_split_axis_and_index_for_corner
// {
// typename Elements::iterator f = elements_copy.begin() + index_first;
// typename Elements::iterator l = elements_copy.begin() + index_last;
-// std::nth_element(elements_copy.begin(), f, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
-// std::nth_element(f, l, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
+// // NOTE: for stdlibc++ shipped with gcc 4.8.2 std::nth_element is replaced with std::sort anyway
+// index::detail::nth_element(elements_copy.begin(), f, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
+// index::detail::nth_element(f, l, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
// std::sort(f, l, elements_less); // MAY THROW, BASIC (copy)
// }
@@ -349,7 +351,7 @@ struct nth_element
typedef typename tag<indexable_type>::type indexable_tag;
element_axis_corner_less<element_type, Translator, indexable_tag, Corner, I> less(tr);
- std::nth_element(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
+ index::detail::nth_element(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
}
}
};
diff --git a/boost/geometry/index/equal_to.hpp b/boost/geometry/index/equal_to.hpp
index b0cf098f1d..6b722a89fc 100644
--- a/boost/geometry/index/equal_to.hpp
+++ b/boost/geometry/index/equal_to.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry Index
//
-// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2016 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
@@ -42,6 +42,15 @@ struct equals<T, void>
}
};
+template <typename T>
+struct equals<T *, void>
+{
+ inline static bool apply(const T * v1, const T * v2)
+ {
+ return v1 == v2;
+ }
+};
+
template <typename Tuple, size_t I, size_t N>
struct tuple_equals
{
diff --git a/boost/geometry/index/parameters.hpp b/boost/geometry/index/parameters.hpp
index 2b94907686..1a9469c103 100644
--- a/boost/geometry/index/parameters.hpp
+++ b/boost/geometry/index/parameters.hpp
@@ -2,7 +2,7 @@
//
// R-tree algorithms parameters
//
-// Copyright (c) 2011-2013 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,14 @@
#ifndef BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
#define BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
+
#include <limits>
+#include <boost/mpl/assert.hpp>
+
+#include <boost/geometry/index/detail/exception.hpp>
+
+
namespace boost { namespace geometry { namespace index {
namespace detail {
@@ -156,8 +162,8 @@ public:
\param max_elements Maximum number of elements in nodes.
\param min_elements Minimum number of elements in nodes. Default: 0.3*Max.
*/
- dynamic_linear(size_t max_elements,
- size_t min_elements = detail::default_min_elements_d())
+ explicit dynamic_linear(size_t max_elements,
+ size_t min_elements = detail::default_min_elements_d())
: m_max_elements(max_elements)
, m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
{
@@ -185,8 +191,8 @@ public:
\param max_elements Maximum number of elements in nodes.
\param min_elements Minimum number of elements in nodes. Default: 0.3*Max.
*/
- dynamic_quadratic(size_t max_elements,
- size_t min_elements = detail::default_min_elements_d())
+ explicit dynamic_quadratic(size_t max_elements,
+ size_t min_elements = detail::default_min_elements_d())
: m_max_elements(max_elements)
, m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
{
@@ -222,10 +228,10 @@ public:
nearly minimum overlap cost, otherwise all leafs are analyzed
and true minimum overlap cost is calculated. Default: 32.
*/
- dynamic_rstar(size_t max_elements,
- size_t min_elements = detail::default_min_elements_d(),
- size_t reinserted_elements = detail::default_rstar_reinserted_elements_d(),
- size_t overlap_cost_threshold = 32)
+ explicit dynamic_rstar(size_t max_elements,
+ size_t min_elements = detail::default_min_elements_d(),
+ size_t reinserted_elements = detail::default_rstar_reinserted_elements_d(),
+ size_t overlap_cost_threshold = 32)
: m_max_elements(max_elements)
, m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
, m_reinserted_elements(detail::default_rstar_reinserted_elements_d_calc(max_elements, reinserted_elements))
diff --git a/boost/geometry/io/wkt/read.hpp b/boost/geometry/io/wkt/read.hpp
index 148a5769dd..236690dc2c 100644
--- a/boost/geometry/io/wkt/read.hpp
+++ b/boost/geometry/io/wkt/read.hpp
@@ -3,6 +3,7 @@
// 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.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015.
// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
@@ -31,6 +32,7 @@
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_reference.hpp>
@@ -139,15 +141,15 @@ struct parsing_assigner
}
catch(boost::bad_lexical_cast const& blc)
{
- throw read_wkt_exception(blc.what(), it, end, wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception(blc.what(), it, end, wkt));
}
catch(std::exception const& e)
{
- throw read_wkt_exception(e.what(), it, end, wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception(e.what(), it, end, wkt));
}
catch(...)
{
- throw read_wkt_exception("", it, end, wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("", it, end, wkt));
}
parsing_assigner<Point, Dimension + 1, DimensionCount>::apply(
@@ -175,7 +177,7 @@ inline void handle_open_parenthesis(Iterator& it,
{
if (it == end || *it != "(")
{
- throw read_wkt_exception("Expected '('", it, end, wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Expected '('", it, end, wkt));
}
++it;
}
@@ -192,7 +194,7 @@ inline void handle_close_parenthesis(Iterator& it,
}
else
{
- throw read_wkt_exception("Expected ')'", it, end, wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Expected ')'", it, end, wkt));
}
}
@@ -203,7 +205,7 @@ inline void check_end(Iterator& it,
{
if (it != end)
{
- throw read_wkt_exception("Too much tokens", it, end, wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Too many tokens", it, end, wkt));
}
}
@@ -529,7 +531,7 @@ inline bool initialize(tokenizer const& tokens,
if (has_z && dimension<Geometry>::type::value < 3)
{
- throw read_wkt_exception("Z only allowed for 3 or more dimensions", wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Z only allowed for 3 or more dimensions", wkt));
}
#if defined(_MSC_VER)
@@ -545,7 +547,7 @@ inline bool initialize(tokenizer const& tokens,
return true;
}
- throw read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt));
}
@@ -702,7 +704,7 @@ struct box_parser
}
else
{
- throw read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt));
}
typedef typename point_type<Box>::type point_type;
@@ -729,7 +731,7 @@ struct box_parser
}
else
{
- throw read_wkt_exception("Box should have 2,4 or 5 points", wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Box should have 2,4 or 5 points", wkt));
}
geometry::detail::assign_point_to_index<min_corner>(points.front(), box);
@@ -760,7 +762,7 @@ struct segment_parser
}
else
{
- throw read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt));
}
typedef typename point_type<Segment>::type point_type;
@@ -776,7 +778,7 @@ struct segment_parser
}
else
{
- throw read_wkt_exception("Segment should have 2 points", wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Segment should have 2 points", wkt));
}
}
diff --git a/boost/geometry/policies/robustness/segment_ratio.hpp b/boost/geometry/policies/robustness/segment_ratio.hpp
index f3dbabe70a..9b313fdfaf 100644
--- a/boost/geometry/policies/robustness/segment_ratio.hpp
+++ b/boost/geometry/policies/robustness/segment_ratio.hpp
@@ -145,11 +145,10 @@ public :
m_approximation =
m_denominator == 0 ? 0
- : boost::numeric_cast<double>
- (
- boost::numeric_cast<fp_type>(m_numerator) * scale()
- / boost::numeric_cast<fp_type>(m_denominator)
- );
+ : (
+ boost::numeric_cast<fp_type>(m_numerator) * scale()
+ / boost::numeric_cast<fp_type>(m_denominator)
+ );
}
inline bool is_zero() const { return math::equals(m_numerator, 0); }
@@ -187,7 +186,7 @@ public :
return false;
}
- static fp_type const small_part_of_scale = scale() / 100.0;
+ static fp_type const small_part_of_scale = scale() / 100;
return m_approximation < small_part_of_scale
|| m_approximation > scale() - small_part_of_scale;
}
@@ -236,7 +235,14 @@ public :
private :
- typedef typename promote_floating_point<Type>::type fp_type;
+ // NOTE: if this typedef is used then fp_type is non-fundamental type
+ // if Type is non-fundamental type
+ //typedef typename promote_floating_point<Type>::type fp_type;
+
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_float<Type>::value, Type, double
+ >::type fp_type;
Type m_numerator;
Type m_denominator;
diff --git a/boost/geometry/strategies/agnostic/point_in_point.hpp b/boost/geometry/strategies/agnostic/point_in_point.hpp
index e4f9bec4c6..c6e2b63623 100644
--- a/boost/geometry/strategies/agnostic/point_in_point.hpp
+++ b/boost/geometry/strategies/agnostic/point_in_point.hpp
@@ -1,12 +1,13 @@
// 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_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP
@@ -41,41 +42,12 @@ struct point_in_point
namespace services
{
-template <typename Point1, typename Point2>
-struct default_strategy<point_tag, point_tag, point_tag, point_tag, cartesian_tag, cartesian_tag, Point1, Point2>
-{
- typedef strategy::within::point_in_point<Point1, Point2> type;
-};
-
-template <typename Point1, typename Point2>
-struct default_strategy<point_tag, point_tag, point_tag, point_tag, spherical_tag, spherical_tag, Point1, Point2>
-{
- typedef strategy::within::point_in_point<Point1, Point2> type;
-};
-
-template <typename Point1, typename Point2, typename AnyCS1, typename AnyCS2>
-struct default_strategy<point_tag, point_tag, point_tag, point_tag, AnyCS1, AnyCS2, Point1, Point2>
+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>
{
- typedef strategy::within::point_in_point<Point1, Point2> type;
+ typedef strategy::within::point_in_point<Point, typename point_type<PointLike>::type> type;
};
-template <typename Point, typename MultiPoint>
-struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, cartesian_tag, cartesian_tag, Point, MultiPoint>
-{
- typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;
-};
-
-template <typename Point, typename MultiPoint>
-struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, spherical_tag, spherical_tag, Point, MultiPoint>
-{
- typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;
-};
-
-template <typename Point, typename MultiPoint, typename AnyCS1, typename AnyCS2>
-struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, AnyCS1, AnyCS2, Point, MultiPoint>
-{
- typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;
-};
} // namespace services
@@ -85,45 +57,14 @@ struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag,
}} // namespace strategy::within
-
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
-template <typename Point1, typename Point2>
-struct default_strategy<point_tag, point_tag, point_tag, point_tag, cartesian_tag, cartesian_tag, Point1, Point2>
-{
- typedef strategy::within::point_in_point<Point1, Point2> type;
-};
-
-template <typename Point1, typename Point2>
-struct default_strategy<point_tag, point_tag, point_tag, point_tag, spherical_tag, spherical_tag, Point1, Point2>
-{
- typedef strategy::within::point_in_point<Point1, Point2> type;
-};
-
-template <typename Point1, typename Point2, typename AnyCS1, typename AnyCS2>
-struct default_strategy<point_tag, point_tag, point_tag, point_tag, AnyCS1, AnyCS2, Point1, Point2>
-{
- typedef strategy::within::point_in_point<Point1, Point2> type;
-};
-
-template <typename Point, typename MultiPoint>
-struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, cartesian_tag, cartesian_tag, Point, MultiPoint>
-{
- typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;
-};
-
-template <typename Point, typename MultiPoint>
-struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, spherical_tag, spherical_tag, Point, MultiPoint>
-{
- typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;
-};
-
-template <typename Point, typename MultiPoint, typename AnyCS1, typename AnyCS2>
-struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, AnyCS1, AnyCS2, Point, MultiPoint>
+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>
{
- typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;
+ typedef strategy::within::point_in_point<Point, typename point_type<PointLike>::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 9e2ec2c4ff..3e7e258788 100644
--- a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
+++ b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013, 2014, 2016.
-// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2016, 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
@@ -314,6 +314,7 @@ struct winding_calculate_count<Point, CalculationType, cartesian_tag>
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
+\tparam SideStrategy Side strategy
\tparam CalculationType \tparam_calculation
\author Barend Gehrels
\note The implementation is inspired by terralib http://www.terralib.org (LGPL)
@@ -329,6 +330,10 @@ template
<
typename Point,
typename PointOfSegment = Point,
+ typename SideStrategy = typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<Point>::type
+ >::type,
typename CalculationType = void
>
class winding
@@ -339,14 +344,7 @@ class winding
PointOfSegment,
CalculationType
>::type calculation_type;
-
-
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<Point>::type
- >::type strategy_side_type;
-
-
+
/*! subclass to keep state */
class counter
{
@@ -371,7 +369,6 @@ class winding
};
-
static inline int check_segment(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
counter& state, bool& eq1, bool& eq2)
@@ -390,16 +387,22 @@ class winding
}
-public :
+public:
+ winding()
+ {}
+
+ explicit winding(SideStrategy const& side_strategy)
+ : m_side_strategy(side_strategy)
+ {}
// Typedefs and static methods to fulfill the concept
typedef Point point_type;
typedef PointOfSegment segment_point_type;
typedef counter state_type;
- static inline bool apply(Point const& point,
- PointOfSegment const& s1, PointOfSegment const& s2,
- counter& state)
+ inline bool apply(Point const& point,
+ PointOfSegment const& s1, PointOfSegment const& s2,
+ counter& state) const
{
typedef typename cs_tag<Point>::type cs_t;
@@ -418,7 +421,7 @@ public :
else // count == 2 || count == -2
{
// 1 left, -1 right
- side = strategy_side_type::apply(s1, s2, point);
+ side = m_side_strategy.apply(s1, s2, point);
}
if (side == 0)
@@ -445,6 +448,9 @@ public :
{
return state.code();
}
+
+private:
+ SideStrategy m_side_strategy;
};
@@ -453,29 +459,26 @@ public :
namespace services
{
-// Register using "areal_tag" for ring, polygon, multi-polygon
-template <typename AnyTag, typename Point, typename Geometry>
-struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, cartesian_tag, cartesian_tag, Point, Geometry>
+template <typename Point, typename Geometry, typename AnyTag>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
-template <typename AnyTag, typename Point, typename Geometry>
-struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, spherical_tag, spherical_tag, Point, Geometry>
+template <typename Point, typename Geometry, typename AnyTag>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
-// TODO: use linear_tag and pointlike_tag the same way how areal_tag is used
-
template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, cartesian_tag, cartesian_tag, Point, Geometry>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, spherical_tag, spherical_tag, Point, Geometry>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
@@ -488,34 +491,30 @@ struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, spherical_tag, sph
}} // namespace strategy::within
-
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
-// Register using "areal_tag" for ring, polygon, multi-polygon
-template <typename AnyTag, typename Point, typename Geometry>
-struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, cartesian_tag, cartesian_tag, Point, Geometry>
+template <typename Point, typename Geometry, typename AnyTag>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
-template <typename AnyTag, typename Point, typename Geometry>
-struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, spherical_tag, spherical_tag, Point, Geometry>
+template <typename Point, typename Geometry, typename AnyTag>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
-// TODO: use linear_tag and pointlike_tag the same way how areal_tag is used
-
template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, cartesian_tag, cartesian_tag, Point, Geometry>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, spherical_tag, spherical_tag, Point, Geometry>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
diff --git a/boost/geometry/strategies/agnostic/relate.hpp b/boost/geometry/strategies/agnostic/relate.hpp
deleted file mode 100644
index 676207694f..0000000000
--- a/boost/geometry/strategies/agnostic/relate.hpp
+++ /dev/null
@@ -1,122 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2014-2015 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_STRATEGY_AGNOSTIC_RELATE_HPP
-#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP
-
-#include <boost/geometry/algorithms/relate.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-namespace strategy { namespace relate
-{
-
-template <typename Geometry1, typename Geometry2, typename StaticMask>
-struct relate
-{
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
- {
- return geometry::relate(geometry1, geometry2, StaticMask());
- }
-};
-
-} // namespace relate
-
-namespace within
-{
-
-#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-
-namespace services
-{
-
-
-template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>
-struct default_strategy<AnyTag1, AnyTag2, AnyTag1, AnyTag2, AnyCS, AnyCS, Geometry1, Geometry2>
-{
- typedef strategy::relate::relate
- <
- Geometry1,
- Geometry2,
- typename detail::de9im::static_mask_within_type
- <
- Geometry1, Geometry2
- >::type
- > type;
-};
-
-template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>
-struct default_strategy<AnyTag1, AnyTag2, AnyTag1, areal_tag, AnyCS, AnyCS, Geometry1, Geometry2>
-{
- typedef strategy::relate::relate
- <
- Geometry1,
- Geometry2,
- typename detail::de9im::static_mask_within_type
- <
- Geometry1, Geometry2
- >::type
- > type;
-};
-
-
-} // namespace services
-
-#endif
-
-
-}} // namespace strategy::within
-
-
-
-#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-namespace strategy { namespace covered_by { namespace services
-{
-
-
-template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>
-struct default_strategy<AnyTag1, AnyTag2, AnyTag1, AnyTag2, AnyCS, AnyCS, Geometry1, Geometry2>
-{
- typedef strategy::relate::relate
- <
- Geometry1,
- Geometry2,
- typename detail::de9im::static_mask_covered_by_type
- <
- Geometry1, Geometry2
- >::type
- > type;
-};
-
-template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>
-struct default_strategy<AnyTag1, AnyTag2, AnyTag1, areal_tag, AnyCS, AnyCS, Geometry1, Geometry2>
-{
- typedef strategy::relate::relate
- <
- Geometry1,
- Geometry2,
- typename detail::de9im::static_mask_covered_by_type
- <
- Geometry1, Geometry2
- >::type
- > type;
-};
-
-
-}}} // namespace strategy::covered_by::services
-#endif
-
-
-}} // namespace boost::geometry
-
-
-#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP
diff --git a/boost/geometry/strategies/azimuth.hpp b/boost/geometry/strategies/azimuth.hpp
new file mode 100644
index 0000000000..8044d3933b
--- /dev/null
+++ b/boost/geometry/strategies/azimuth.hpp
@@ -0,0 +1,44 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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_AZIMUTH_HPP
+#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_HPP
+
+#include <boost/mpl/assert.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace azimuth { namespace services
+{
+
+/*!
+\brief Traits class binding a default azimuth strategy to a coordinate system
+\ingroup util
+\tparam CSTag tag of coordinate system
+\tparam CalculationType \tparam_calculation
+*/
+template <typename CSTag, typename CalculationType = void>
+struct default_strategy
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_TYPE
+ , (types<CSTag>)
+ );
+};
+
+}}} // namespace strategy::azimuth::services
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_HPP
diff --git a/boost/geometry/strategies/cartesian/area_surveyor.hpp b/boost/geometry/strategies/cartesian/area_surveyor.hpp
index ba76f67946..b3f19b1b1e 100644
--- a/boost/geometry/strategies/cartesian/area_surveyor.hpp
+++ b/boost/geometry/strategies/cartesian/area_surveyor.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2016.
-// Modifications copyright (c) 2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016, 2017.
+// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -25,6 +25,7 @@
//#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/strategies/area.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
diff --git a/boost/geometry/strategies/cartesian/azimuth.hpp b/boost/geometry/strategies/cartesian/azimuth.hpp
new file mode 100644
index 0000000000..62f804e8f5
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/azimuth.hpp
@@ -0,0 +1,49 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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_CARTESIAN_AZIMUTH_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP
+
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace azimuth
+{
+
+template
+<
+ typename CalculationType = void
+>
+class cartesian
+{};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<cartesian_tag, CalculationType>
+{
+ typedef strategy::azimuth::cartesian<CalculationType> type;
+};
+
+}
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}} // namespace strategy::azimuth
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP
diff --git a/boost/geometry/strategies/cartesian/box_in_box.hpp b/boost/geometry/strategies/cartesian/box_in_box.hpp
index 28a6f29336..4641aafcb1 100644
--- a/boost/geometry/strategies/cartesian/box_in_box.hpp
+++ b/boost/geometry/strategies/cartesian/box_in_box.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2015, 2016.
-// Modifications copyright (c) 2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016, 2017.
+// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -238,10 +238,10 @@ namespace within { namespace services
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
+ BoxContained, BoxContaining,
box_tag, box_tag,
- box_tag, areal_tag,
- cartesian_tag, cartesian_tag,
- BoxContained, BoxContaining
+ areal_tag, areal_tag,
+ cartesian_tag, cartesian_tag
>
{
typedef within::box_in_box<BoxContained, BoxContaining> type;
@@ -251,10 +251,10 @@ struct default_strategy
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
+ BoxContained, BoxContaining,
box_tag, box_tag,
- box_tag, areal_tag,
- spherical_tag, spherical_tag,
- BoxContained, BoxContaining
+ areal_tag, areal_tag,
+ spherical_tag, spherical_tag
>
{
typedef within::box_in_box<BoxContained, BoxContaining> type;
@@ -269,10 +269,10 @@ namespace covered_by { namespace services
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
+ BoxContained, BoxContaining,
box_tag, box_tag,
- box_tag, areal_tag,
- cartesian_tag, cartesian_tag,
- BoxContained, BoxContaining
+ areal_tag, areal_tag,
+ cartesian_tag, cartesian_tag
>
{
typedef within::box_in_box
@@ -286,10 +286,10 @@ struct default_strategy
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
+ BoxContained, BoxContaining,
box_tag, box_tag,
- box_tag, areal_tag,
- spherical_tag, spherical_tag,
- BoxContained, BoxContaining
+ areal_tag, areal_tag,
+ spherical_tag, spherical_tag
>
{
typedef within::box_in_box
diff --git a/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp b/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp
new file mode 100644
index 0000000000..4270803322
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp
@@ -0,0 +1,320 @@
+// Boost.Geometry
+
+// 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.
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
+
+// 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
+
+// Use, modification and distribution is subject to the Boost Software 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_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_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/strategies/disjoint.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy { namespace disjoint
+{
+
+namespace detail
+{
+
+template <std::size_t I>
+struct compute_tmin_tmax_per_dim
+{
+ template <typename SegmentPoint, typename Box, typename RelativeDistance>
+ static inline void apply(SegmentPoint const& p0,
+ SegmentPoint const& p1,
+ Box const& box,
+ RelativeDistance& ti_min,
+ RelativeDistance& ti_max,
+ RelativeDistance& diff)
+ {
+ typedef typename coordinate_type<Box>::type box_coordinate_type;
+ typedef typename coordinate_type
+ <
+ SegmentPoint
+ >::type point_coordinate_type;
+
+ RelativeDistance c_p0 = boost::numeric_cast
+ <
+ point_coordinate_type
+ >( geometry::get<I>(p0) );
+
+ RelativeDistance c_p1 = boost::numeric_cast
+ <
+ point_coordinate_type
+ >( geometry::get<I>(p1) );
+
+ RelativeDistance c_b_min = boost::numeric_cast
+ <
+ box_coordinate_type
+ >( geometry::get<geometry::min_corner, I>(box) );
+
+ RelativeDistance c_b_max = boost::numeric_cast
+ <
+ box_coordinate_type
+ >( geometry::get<geometry::max_corner, I>(box) );
+
+ if ( geometry::get<I>(p1) >= geometry::get<I>(p0) )
+ {
+ diff = c_p1 - c_p0;
+ ti_min = c_b_min - c_p0;
+ ti_max = c_b_max - c_p0;
+ }
+ else
+ {
+ diff = c_p0 - c_p1;
+ ti_min = c_p0 - c_b_max;
+ ti_max = c_p0 - c_b_min;
+ }
+ }
+};
+
+
+template
+<
+ typename RelativeDistance,
+ typename SegmentPoint,
+ typename Box,
+ std::size_t I,
+ std::size_t Dimension
+>
+struct disjoint_segment_box_impl
+{
+ template <typename RelativeDistancePair>
+ static inline bool apply(SegmentPoint const& p0,
+ SegmentPoint const& p1,
+ Box const& box,
+ RelativeDistancePair& t_min,
+ RelativeDistancePair& t_max)
+ {
+ RelativeDistance ti_min, ti_max, diff;
+
+ compute_tmin_tmax_per_dim<I>::apply(p0, p1, box, ti_min, ti_max, diff);
+
+ if ( geometry::math::equals(diff, 0) )
+ {
+ if ( (geometry::math::equals(t_min.second, 0)
+ && t_min.first > ti_max)
+ ||
+ (geometry::math::equals(t_max.second, 0)
+ && t_max.first < ti_min)
+ ||
+ (math::sign(ti_min) * math::sign(ti_max) > 0) )
+ {
+ return true;
+ }
+ }
+
+ RelativeDistance t_min_x_diff = t_min.first * diff;
+ RelativeDistance t_max_x_diff = t_max.first * diff;
+
+ if ( t_min_x_diff > ti_max * t_min.second
+ || t_max_x_diff < ti_min * t_max.second )
+ {
+ return true;
+ }
+
+ if ( ti_min * t_min.second > t_min_x_diff )
+ {
+ t_min.first = ti_min;
+ t_min.second = diff;
+ }
+ if ( ti_max * t_max.second < t_max_x_diff )
+ {
+ t_max.first = ti_max;
+ t_max.second = diff;
+ }
+
+ if ( t_min.first > t_min.second || t_max.first < 0 )
+ {
+ return true;
+ }
+
+ return disjoint_segment_box_impl
+ <
+ RelativeDistance,
+ SegmentPoint,
+ Box,
+ I + 1,
+ Dimension
+ >::apply(p0, p1, box, t_min, t_max);
+ }
+};
+
+
+template
+<
+ typename RelativeDistance,
+ typename SegmentPoint,
+ typename Box,
+ std::size_t Dimension
+>
+struct disjoint_segment_box_impl
+ <
+ RelativeDistance, SegmentPoint, Box, 0, Dimension
+ >
+{
+ static inline bool apply(SegmentPoint const& p0,
+ SegmentPoint const& p1,
+ Box const& box)
+ {
+ std::pair<RelativeDistance, RelativeDistance> t_min, t_max;
+ RelativeDistance diff;
+
+ compute_tmin_tmax_per_dim<0>::apply(p0, p1, box,
+ t_min.first, t_max.first, diff);
+
+ if ( geometry::math::equals(diff, 0) )
+ {
+ if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; }
+ if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; }
+
+ if (math::sign(t_min.first) * math::sign(t_max.first) > 0)
+ {
+ return true;
+ }
+ }
+
+ if ( t_min.first > diff || t_max.first < 0 )
+ {
+ return true;
+ }
+
+ t_min.second = t_max.second = diff;
+
+ return disjoint_segment_box_impl
+ <
+ RelativeDistance, SegmentPoint, Box, 1, Dimension
+ >::apply(p0, p1, box, t_min, t_max);
+ }
+};
+
+
+template
+<
+ typename RelativeDistance,
+ typename SegmentPoint,
+ typename Box,
+ std::size_t Dimension
+>
+struct disjoint_segment_box_impl
+ <
+ RelativeDistance, SegmentPoint, Box, Dimension, Dimension
+ >
+{
+ template <typename RelativeDistancePair>
+ static inline bool apply(SegmentPoint const&, SegmentPoint const&,
+ Box const&,
+ RelativeDistancePair&, RelativeDistancePair&)
+ {
+ return false;
+ }
+};
+
+} // namespace detail
+
+// 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
+{
+ 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)
+ {
+ assert_dimension_equal<Segment, Box>();
+
+ typedef typename util::calculation_type::geometric::binary
+ <
+ Segment, Box, void
+ >::type relative_distance_type;
+
+ typedef typename point_type<Segment>::type segment_point_type;
+ segment_point_type p0, p1;
+ geometry::detail::assign_point_from_index<0>(segment, p0);
+ geometry::detail::assign_point_from_index<1>(segment, p1);
+
+ return detail::disjoint_segment_box_impl
+ <
+ relative_distance_type, segment_point_type, Box,
+ 0, dimension<Box>::value
+ >::apply(p0, p1, box);
+ }
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+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>
+{
+ typedef disjoint::segment_box type;
+};
+
+template <typename Box, typename Linear, typename LinearTag>
+struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1>
+{
+ typedef disjoint::segment_box type;
+};
+
+
+} // namespace services
+
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}}}} // namespace boost::geometry::strategy::disjoint
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP
diff --git a/boost/geometry/strategies/cartesian/envelope_segment.hpp b/boost/geometry/strategies/cartesian/envelope_segment.hpp
new file mode 100644
index 0000000000..0ddbf12a41
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/envelope_segment.hpp
@@ -0,0 +1,71 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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_CARTESIAN_ENVELOPE_SEGMENT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP
+
+
+#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace envelope
+{
+
+template
+<
+ typename CalculationType = void
+>
+class cartesian_segment
+{
+public :
+
+ template <typename Point1, typename Point2, typename Box>
+ inline void
+ apply(Point1 const& point1, Point2 const& point2, Box& box) const
+ {
+ geometry::detail::envelope::envelope_one_segment
+ <
+ 0,
+ dimension<Point1>::value
+ >
+ ::apply(point1,
+ point2,
+ box,
+ strategy::envelope::cartesian_segment<CalculationType>());
+ }
+
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<cartesian_tag, CalculationType>
+{
+ typedef strategy::envelope::cartesian_segment<CalculationType> type;
+};
+
+}
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::envelope
+
+}} //namepsace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP
diff --git a/boost/geometry/strategies/cartesian/cart_intersect.hpp b/boost/geometry/strategies/cartesian/intersection.hpp
index 0cb5d75457..20b6b93367 100644
--- a/boost/geometry/strategies/cartesian/cart_intersect.hpp
+++ b/boost/geometry/strategies/cartesian/intersection.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014, 2016.
-// Modifications copyright (c) 2014-2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016, 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
@@ -33,13 +33,16 @@
#include <boost/geometry/util/promote_integral.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
-// Temporary / will be Strategy as template parameter
-#include <boost/geometry/strategies/side.hpp>
+#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/side_by_triangle.hpp>
-
-#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
+#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
@@ -61,10 +64,74 @@ namespace strategy { namespace intersection
/*!
\see http://mathworld.wolfram.com/Line-LineIntersection.html
*/
-template <typename Policy, typename CalculationType = void>
-struct relate_cartesian_segments
+template
+<
+ typename CalculationType = void
+>
+struct cartesian_segments
{
- typedef typename Policy::return_type return_type;
+ typedef side::side_by_triangle<CalculationType> side_strategy_type;
+
+ static inline side_strategy_type get_side_strategy()
+ {
+ return side_strategy_type();
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ struct point_in_geometry_strategy
+ {
+ typedef strategy::within::winding
+ <
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type,
+ side_strategy_type,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry1, typename Geometry2>
+ static inline typename point_in_geometry_strategy<Geometry1, Geometry2>::type
+ get_point_in_geometry_strategy()
+ {
+ typedef typename point_in_geometry_strategy
+ <
+ Geometry1, Geometry2
+ >::type strategy_type;
+ return strategy_type();
+ }
+
+ template <typename Geometry>
+ struct area_strategy
+ {
+ typedef area::surveyor
+ <
+ typename point_type<Geometry>::type,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry>
+ static inline typename area_strategy<Geometry>::type get_area_strategy()
+ {
+ typedef typename area_strategy<Geometry>::type strategy_type;
+ return strategy_type();
+ }
+
+ template <typename Geometry>
+ struct distance_strategy
+ {
+ typedef distance::pythagoras
+ <
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry>
+ static inline typename distance_strategy<Geometry>::type get_distance_strategy()
+ {
+ typedef typename distance_strategy<Geometry>::type strategy_type;
+ return strategy_type();
+ }
template <typename CoordinateType, typename SegmentRatio>
struct segment_intersection_info
@@ -144,9 +211,16 @@ struct relate_cartesian_segments
// Relate segments a and b
- template <typename Segment1, typename Segment2, typename RobustPolicy>
- static inline return_type apply(Segment1 const& a, Segment2 const& b,
- RobustPolicy const& robust_policy)
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename Policy,
+ typename RobustPolicy
+ >
+ static inline typename Policy::return_type
+ apply(Segment1 const& a, Segment2 const& b,
+ Policy const& policy, RobustPolicy const& robust_policy)
{
// type them all as in Segment1 - TODO reconsider this, most precise?
typedef typename geometry::point_type<Segment1>::type point_type;
@@ -169,18 +243,25 @@ struct relate_cartesian_segments
geometry::recalculate(b0_rob, b0, robust_policy);
geometry::recalculate(b1_rob, b1, robust_policy);
- return apply(a, b, robust_policy, a0_rob, a1_rob, b0_rob, b1_rob);
+ return apply(a, b, policy, robust_policy, a0_rob, a1_rob, b0_rob, b1_rob);
}
// The main entry-routine, calculating intersections of segments a / b
// NOTE: Robust* types may be the same as Segments' point types
- template <typename Segment1, typename Segment2,
- typename RobustPolicy,
- typename RobustPoint1, typename RobustPoint2>
- static inline return_type apply(Segment1 const& a, Segment2 const& b,
- RobustPolicy const& /*robust_policy*/,
- RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,
- RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2)
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename Policy,
+ typename RobustPolicy,
+ typename RobustPoint1,
+ typename RobustPoint2
+ >
+ static inline typename Policy::return_type
+ apply(Segment1 const& a, Segment2 const& b,
+ Policy const&, RobustPolicy const& /*robust_policy*/,
+ RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,
+ RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2)
{
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
@@ -197,14 +278,9 @@ struct relate_cartesian_segments
;
}
- typedef typename select_calculation_type
- <Segment1, Segment2, CalculationType>::type coordinate_type;
-
- typedef side::side_by_triangle<coordinate_type> side;
-
side_info sides;
- sides.set<0>(side::apply(robust_b1, robust_b2, robust_a1),
- side::apply(robust_b1, robust_b2, robust_a2));
+ sides.set<0>(side_strategy_type::apply(robust_b1, robust_b2, robust_a1),
+ side_strategy_type::apply(robust_b1, robust_b2, robust_a2));
if (sides.same<0>())
{
@@ -212,8 +288,8 @@ struct relate_cartesian_segments
return Policy::disjoint();
}
- sides.set<1>(side::apply(robust_a1, robust_a2, robust_b1),
- side::apply(robust_a1, robust_a2, robust_b2));
+ sides.set<1>(side_strategy_type::apply(robust_a1, robust_a2, robust_b1),
+ side_strategy_type::apply(robust_a1, robust_a2, robust_b2));
if (sides.same<1>())
{
@@ -230,16 +306,16 @@ struct relate_cartesian_segments
>::type robust_coordinate_type;
typedef typename segment_ratio_type
- <
- typename geometry::point_type<Segment1>::type, // TODO: most precise point?
- RobustPolicy
- >::type ratio_type;
+ <
+ typename geometry::point_type<Segment1>::type, // TODO: most precise point?
+ RobustPolicy
+ >::type ratio_type;
segment_intersection_info
- <
- coordinate_type,
- ratio_type
- > sinfo;
+ <
+ typename select_calculation_type<Segment1, Segment2, CalculationType>::type,
+ ratio_type
+ > sinfo;
sinfo.dx_a = get<1, 0>(a) - get<0, 0>(a); // distance in x-dir
sinfo.dx_b = get<1, 0>(b) - get<0, 0>(b);
@@ -303,14 +379,14 @@ struct relate_cartesian_segments
if (collinear_use_first.first)
{
- return relate_collinear<0, ratio_type>(a, b,
+ return relate_collinear<0, Policy, ratio_type>(a, b,
robust_a1, robust_a2, robust_b1, robust_b2,
a_is_point, b_is_point);
}
else
{
// Y direction contains larger segments (maybe dx is zero)
- return relate_collinear<1, ratio_type>(a, b,
+ return relate_collinear<1, Policy, ratio_type>(a, b,
robust_a1, robust_a2, robust_b1, robust_b2,
a_is_point, b_is_point);
}
@@ -358,33 +434,35 @@ private:
template
<
std::size_t Dimension,
+ typename Policy,
typename RatioType,
typename Segment1,
typename Segment2,
typename RobustPoint1,
typename RobustPoint2
>
- static inline return_type relate_collinear(Segment1 const& a,
- Segment2 const& b,
- RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,
- RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2,
- bool a_is_point, bool b_is_point)
+ static inline typename Policy::return_type
+ relate_collinear(Segment1 const& a,
+ Segment2 const& b,
+ RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,
+ RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2,
+ bool a_is_point, bool b_is_point)
{
if (a_is_point)
{
- return relate_one_degenerate<RatioType>(a,
+ return relate_one_degenerate<Policy, RatioType>(a,
get<Dimension>(robust_a1),
get<Dimension>(robust_b1), get<Dimension>(robust_b2),
true);
}
if (b_is_point)
{
- return relate_one_degenerate<RatioType>(b,
+ return relate_one_degenerate<Policy, RatioType>(b,
get<Dimension>(robust_b1),
get<Dimension>(robust_a1), get<Dimension>(robust_a2),
false);
}
- return relate_collinear<RatioType>(a, b,
+ return relate_collinear<Policy, RatioType>(a, b,
get<Dimension>(robust_a1),
get<Dimension>(robust_a2),
get<Dimension>(robust_b1),
@@ -394,17 +472,17 @@ private:
/// Relate segments known collinear
template
<
+ typename Policy,
typename RatioType,
typename Segment1,
typename Segment2,
typename RobustType1,
typename RobustType2
>
- static inline return_type relate_collinear(Segment1 const& a
- , Segment2 const& b
- , RobustType1 oa_1, RobustType1 oa_2
- , RobustType2 ob_1, RobustType2 ob_2
- )
+ static inline typename Policy::return_type
+ relate_collinear(Segment1 const& a, Segment2 const& b,
+ RobustType1 oa_1, RobustType1 oa_2,
+ RobustType2 ob_1, RobustType2 ob_2)
{
// Calculate the ratios where a starts in b, b starts in a
// a1--------->a2 (2..7)
@@ -496,17 +574,16 @@ private:
/// Relate segments where one is degenerate
template
<
+ typename Policy,
typename RatioType,
typename DegenerateSegment,
typename RobustType1,
typename RobustType2
>
- static inline return_type relate_one_degenerate(
- DegenerateSegment const& degenerate_segment
- , RobustType1 d
- , RobustType2 s1, RobustType2 s2
- , bool a_degenerate
- )
+ static inline typename Policy::return_type
+ relate_one_degenerate(DegenerateSegment const& degenerate_segment,
+ RobustType1 d, RobustType2 s1, RobustType2 s2,
+ bool a_degenerate)
{
// Calculate the ratios where ds starts in s
// a1--------->a2 (2..6)
@@ -546,10 +623,10 @@ private:
namespace services
{
-template <typename Policy, typename CalculationType>
-struct default_strategy<cartesian_tag, Policy, CalculationType>
+template <typename CalculationType>
+struct default_strategy<cartesian_tag, CalculationType>
{
- typedef relate_cartesian_segments<Policy, CalculationType> type;
+ typedef cartesian_segments<CalculationType> type;
};
} // namespace services
@@ -558,6 +635,69 @@ struct default_strategy<cartesian_tag, Policy, CalculationType>
}} // namespace strategy::intersection
+namespace strategy
+{
+
+namespace within { namespace services
+{
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, linear_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, polygonal_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, linear_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, polygonal_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+}} // within::services
+
+namespace covered_by { namespace services
+{
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, linear_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, polygonal_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, linear_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, polygonal_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+}} // within::services
+
+} // strategy
+
}} // namespace boost::geometry
diff --git a/boost/geometry/strategies/cartesian/point_in_box.hpp b/boost/geometry/strategies/cartesian/point_in_box.hpp
index 227a98f2ad..1c14125a6d 100644
--- a/boost/geometry/strategies/cartesian/point_in_box.hpp
+++ b/boost/geometry/strategies/cartesian/point_in_box.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015-2016.
-// Modifications copyright (c) 2015-2016, 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
@@ -219,10 +219,10 @@ namespace within { namespace services
template <typename Point, typename Box>
struct default_strategy
<
+ Point, Box,
point_tag, box_tag,
- point_tag, areal_tag,
- cartesian_tag, cartesian_tag,
- Point, Box
+ pointlike_tag, areal_tag,
+ cartesian_tag, cartesian_tag
>
{
typedef within::point_in_box<Point, Box> type;
@@ -232,10 +232,10 @@ struct default_strategy
template <typename Point, typename Box>
struct default_strategy
<
+ Point, Box,
point_tag, box_tag,
- point_tag, areal_tag,
- spherical_tag, spherical_tag,
- Point, Box
+ pointlike_tag, areal_tag,
+ spherical_tag, spherical_tag
>
{
typedef within::point_in_box<Point, Box> type;
@@ -252,10 +252,10 @@ namespace covered_by { namespace services
template <typename Point, typename Box>
struct default_strategy
<
+ Point, Box,
point_tag, box_tag,
- point_tag, areal_tag,
- cartesian_tag, cartesian_tag,
- Point, Box
+ pointlike_tag, areal_tag,
+ cartesian_tag, cartesian_tag
>
{
typedef within::point_in_box
@@ -269,10 +269,10 @@ struct default_strategy
template <typename Point, typename Box>
struct default_strategy
<
+ Point, Box,
point_tag, box_tag,
- point_tag, areal_tag,
- spherical_tag, spherical_tag,
- Point, Box
+ pointlike_tag, areal_tag,
+ spherical_tag, spherical_tag
>
{
typedef within::point_in_box
diff --git a/boost/geometry/strategies/covered_by.hpp b/boost/geometry/strategies/covered_by.hpp
index a5aae7703b..363e34b68f 100644
--- a/boost/geometry/strategies/covered_by.hpp
+++ b/boost/geometry/strategies/covered_by.hpp
@@ -4,6 +4,11 @@
// 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.
@@ -16,6 +21,12 @@
#include <boost/mpl/assert.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+
namespace boost { namespace geometry
{
@@ -31,23 +42,39 @@ namespace services
/*!
\brief Traits class binding a covered_by determination strategy to a coordinate system
\ingroup covered_by
-\tparam TagContained tag (possibly casted) of point-type
-\tparam TagContained tag (possibly casted) of (possibly) containing type
-\tparam CsTagContained tag of coordinate system of point-type
-\tparam CsTagContaining tag of coordinate system of (possibly) containing type
-\tparam Geometry geometry-type of input (often point, or box)
+\tparam GeometryContained geometry-type of input (possibly) contained type
\tparam GeometryContaining geometry-type of input (possibly) containing type
+\tparam TagContained casted tag of (possibly) contained type
+\tparam TagContaining casted tag of (possibly) containing type
+\tparam CsTagContained tag of coordinate system of (possibly) contained type
+\tparam CsTagContaining tag of coordinate system of (possibly) containing type
*/
template
<
- typename TagContained,
- typename TagContaining,
- typename CastedTagContained,
- typename CastedTagContaining,
- typename CsTagContained,
- typename CsTagContaining,
typename GeometryContained,
- typename GeometryContaining
+ typename GeometryContaining,
+ typename TagContained = typename tag<GeometryContained>::type,
+ typename TagContaining = typename tag<GeometryContaining>::type,
+ typename CastedTagContained = typename tag_cast
+ <
+ typename tag<GeometryContained>::type,
+ pointlike_tag, linear_tag, polygonal_tag, areal_tag
+ >::type,
+ typename CastedTagContaining = typename tag_cast
+ <
+ typename tag<GeometryContaining>::type,
+ pointlike_tag, linear_tag, polygonal_tag, areal_tag
+ >::type,
+ typename CsTagContained = typename tag_cast
+ <
+ typename cs_tag<typename point_type<GeometryContained>::type>::type,
+ spherical_tag
+ >::type,
+ typename CsTagContaining = typename tag_cast
+ <
+ typename cs_tag<typename point_type<GeometryContaining>::type>::type,
+ spherical_tag
+ >::type
>
struct default_strategy
{
diff --git a/boost/geometry/strategies/disjoint.hpp b/boost/geometry/strategies/disjoint.hpp
new file mode 100644
index 0000000000..f844cd86ad
--- /dev/null
+++ b/boost/geometry/strategies/disjoint.hpp
@@ -0,0 +1,90 @@
+// 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_STRATEGIES_DISJOINT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_DISJOINT_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/topological_dimension.hpp>
+
+#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/relate.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy { namespace disjoint
+{
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ 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
+>
+struct default_strategy
+ : relate::services::default_strategy
+ <
+ Geometry1, Geometry2
+ >
+{};
+
+template <typename Point, typename Box>
+struct default_strategy<Point, Box, point_tag, box_tag, 0, 2>
+ : strategy::covered_by::services::default_strategy<Point, Box>
+{};
+
+template <typename Box, typename Point>
+struct default_strategy<Box, Point, box_tag, point_tag, 2, 0>
+ : strategy::covered_by::services::default_strategy<Point, Box>
+{};
+
+template <typename MultiPoint, typename Box>
+struct default_strategy<MultiPoint, Box, multi_point_tag, box_tag, 0, 2>
+ : strategy::covered_by::services::default_strategy
+ <
+ typename point_type<MultiPoint>::type,
+ Box
+ >
+{};
+
+template <typename Box, typename MultiPoint>
+struct default_strategy<Box, MultiPoint, box_tag, multi_point_tag, 2, 0>
+ : strategy::covered_by::services::default_strategy
+ <
+ typename point_type<MultiPoint>::type,
+ Box
+ >
+{};
+
+template <typename Box1, typename Box2>
+struct default_strategy<Box1, Box2, box_tag, box_tag, 2, 2>
+{
+ // dummy strategy which will be ignored
+ typedef geometry::default_strategy type;
+};
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}}}} // namespace boost::geometry::strategy::disjoint
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_DISJOINT_HPP
diff --git a/boost/geometry/strategies/envelope.hpp b/boost/geometry/strategies/envelope.hpp
new file mode 100644
index 0000000000..fde9c858a6
--- /dev/null
+++ b/boost/geometry/strategies/envelope.hpp
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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_ENVELOPE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_ENVELOPE_HPP
+
+#include <boost/mpl/assert.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace envelope { namespace services
+{
+
+/*!
+\brief Traits class binding a default envelope strategy to a coordinate system
+\ingroup util
+\tparam CSTag tag of coordinate system
+\tparam CalculationType \tparam_calculation
+*/
+template <typename CSTag, typename CalculationType = void>
+struct default_strategy
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_TYPE
+ , (types<CSTag>)
+ );
+};
+
+}}} // namespace strategy::envelope::services
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_ENVELOPE_HPP
+
diff --git a/boost/geometry/strategies/geographic/area.hpp b/boost/geometry/strategies/geographic/area.hpp
new file mode 100644
index 0000000000..e1d3b09b5a
--- /dev/null
+++ b/boost/geometry/strategies/geographic/area.hpp
@@ -0,0 +1,216 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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_AREA_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AREA_HPP
+
+
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/formulas/area_formulas.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
+
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+
+#include <boost/math/special_functions/atanh.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace area
+{
+
+/*!
+\brief Geographic area calculation
+\ingroup strategies
+\details Geographic area calculation by trapezoidal rule plus integral
+ approximation that gives the ellipsoidal correction
+\tparam PointOfSegment \tparam_segment_point
+\tparam FormulaPolicy Formula used to calculate azimuths
+\tparam SeriesOrder The order of approximation of the geodesic integral
+\tparam Spheroid The spheroid model
+\tparam CalculationType \tparam_calculation
+\author See
+- Danielsen JS, The area under the geodesic. Surv Rev 30(232): 61–66, 1989
+- Charles F.F Karney, Algorithms for geodesics, 2011 https://arxiv.org/pdf/1109.4448.pdf
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
+}
+*/
+template
+<
+ typename PointOfSegment,
+ typename FormulaPolicy = strategy::andoyer,
+ std::size_t SeriesOrder = strategy::default_order<FormulaPolicy>::value,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic
+{
+ // Switch between two kinds of approximation(series in eps and n v.s.series in k ^ 2 and e'^2)
+ static const bool ExpandEpsN = true;
+ // LongSegment Enables special handling of long segments
+ static const bool LongSegment = false;
+
+ //Select default types in case they are not set
+
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename coordinate_type<PointOfSegment>::type,
+ double
+ >::type,
+ CalculationType
+ >::type CT;
+
+protected :
+ struct spheroid_constants
+ {
+ Spheroid m_spheroid;
+ CT const m_a2; // squared equatorial radius
+ 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
+
+ inline spheroid_constants(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ , m_a2(math::sqr(get_radius<0>(spheroid)))
+ , m_e2(formula::flattening<CT>(spheroid)
+ * (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))))
+ {}
+ };
+
+ struct area_sums
+ {
+ CT m_excess_sum;
+ CT m_correction_sum;
+
+ // Keep track if encircles some pole
+ std::size_t m_crosses_prime_meridian;
+
+ inline area_sums()
+ : m_excess_sum(0)
+ , m_correction_sum(0)
+ , m_crosses_prime_meridian(0)
+ {}
+ inline CT area(spheroid_constants spheroid_const) const
+ {
+ CT result;
+
+ CT sum = spheroid_const.m_c2 * m_excess_sum
+ + spheroid_const.m_e2 * spheroid_const.m_a2 * m_correction_sum;
+
+ // If encircles some pole
+ if (m_crosses_prime_meridian % 2 == 1)
+ {
+ std::size_t times_crosses_prime_meridian
+ = 1 + (m_crosses_prime_meridian / 2);
+
+ result = CT(2.0)
+ * geometry::math::pi<CT>()
+ * spheroid_const.m_c2
+ * CT(times_crosses_prime_meridian)
+ - geometry::math::abs(sum);
+
+ if (geometry::math::sign<CT>(sum) == 1)
+ {
+ result = - result;
+ }
+
+ }
+ else
+ {
+ result = sum;
+ }
+
+ return result;
+ }
+ };
+
+public :
+ typedef CT return_type;
+ typedef PointOfSegment segment_point_type;
+ typedef area_sums state_type;
+
+ explicit inline geographic(Spheroid const& spheroid = Spheroid())
+ : m_spheroid_constants(spheroid)
+ {}
+
+ inline void apply(PointOfSegment const& p1,
+ PointOfSegment const& p2,
+ area_sums& state) const
+ {
+
+ if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
+ {
+
+ typedef geometry::formula::area_formulas
+ <
+ CT, SeriesOrder, ExpandEpsN
+ > area_formulas;
+
+ typename area_formulas::return_type_ellipsoidal result =
+ area_formulas::template ellipsoidal<FormulaPolicy::template inverse>
+ (p1, p2, m_spheroid_constants);
+
+ state.m_excess_sum += result.spherical_term;
+ state.m_correction_sum += result.ellipsoidal_term;
+
+ // Keep track whenever a segment crosses the prime meridian
+ geometry::formula::area_formulas<CT>
+ ::crosses_prime_meridian(p1, p2, state);
+ }
+ }
+
+ inline return_type result(area_sums const& state) const
+ {
+ return state.area(m_spheroid_constants);
+ }
+
+private:
+ spheroid_constants m_spheroid_constants;
+
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+
+template <typename Point>
+struct default_strategy<geographic_tag, Point>
+{
+ typedef strategy::area::geographic<Point> type;
+};
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}
+
+}} // namespace strategy::area
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AREA_HPP
diff --git a/boost/geometry/strategies/geographic/azimuth.hpp b/boost/geometry/strategies/geographic/azimuth.hpp
new file mode 100644
index 0000000000..47f59d1033
--- /dev/null
+++ b/boost/geometry/strategies/geographic/azimuth.hpp
@@ -0,0 +1,103 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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_AZIMUTH_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AZIMUTH_HPP
+
+
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/strategies/azimuth.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_void.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace azimuth
+{
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic
+{
+public :
+
+ typedef Spheroid model_type;
+
+ inline geographic()
+ : m_spheroid()
+ {}
+
+ explicit inline geographic(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {}
+
+ inline model_type const& model() const
+ {
+ return m_spheroid;
+ }
+
+ template <typename T>
+ inline void apply(T const& lon1_rad, T const& lat1_rad,
+ T const& lon2_rad, T const& lat2_rad,
+ T& a1, T& a2) const
+ {
+ typedef typename boost::mpl::if_
+ <
+ boost::is_void<CalculationType>, T, CalculationType
+ >::type calc_t;
+
+ typedef typename FormulaPolicy::template inverse<calc_t, false, true, true, 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;
+ a2 = i_res.reverse_azimuth;
+ }
+
+private :
+ Spheroid m_spheroid;
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<geographic_tag, CalculationType>
+{
+ typedef strategy::azimuth::geographic
+ <
+ strategy::andoyer,
+ srs::spheroid<double>,
+ CalculationType
+ > type;
+};
+
+}
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}} // namespace strategy::azimuth
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AZIMUTH_HPP
diff --git a/boost/geometry/strategies/geographic/distance.hpp b/boost/geometry/strategies/geographic/distance.hpp
new file mode 100644
index 0000000000..d3656f449c
--- /dev/null
+++ b/boost/geometry/strategies/geographic/distance.hpp
@@ -0,0 +1,195 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.
+
+// 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
+
+// Use, modification and distribution is subject to the Boost Software 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_DISTANCE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/formulas/andoyer_inverse.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace distance
+{
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic
+{
+public :
+ template <typename Point1, typename Point2>
+ struct calculation_type
+ : promote_floating_point
+ <
+ typename select_calculation_type
+ <
+ Point1,
+ Point2,
+ CalculationType
+ >::type
+ >
+ {};
+
+ typedef Spheroid model_type;
+
+ inline geographic()
+ : m_spheroid()
+ {}
+
+ explicit inline geographic(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {}
+
+ template <typename Point1, typename Point2>
+ inline typename calculation_type<Point1, Point2>::type
+ apply(Point1 const& point1, Point2 const& point2) const
+ {
+ return FormulaPolicy::template inverse
+ <
+ typename calculation_type<Point1, Point2>::type,
+ true, false, false, false, false
+ >::apply(get_as_radian<0>(point1), get_as_radian<1>(point1),
+ get_as_radian<0>(point2), get_as_radian<1>(point2),
+ m_spheroid).distance;
+ }
+
+ inline Spheroid const& model() const
+ {
+ return m_spheroid;
+ }
+
+private :
+ Spheroid m_spheroid;
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType
+>
+struct tag<geographic<FormulaPolicy, Spheroid, CalculationType> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType,
+ typename P1,
+ typename P2
+>
+struct return_type<geographic<FormulaPolicy, Spheroid, CalculationType>, P1, P2>
+ : geographic<FormulaPolicy, Spheroid, CalculationType>::template calculation_type<P1, P2>
+{};
+
+
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType
+>
+struct comparable_type<geographic<FormulaPolicy, Spheroid, CalculationType> >
+{
+ typedef geographic<FormulaPolicy, Spheroid, CalculationType> type;
+};
+
+
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType
+>
+struct get_comparable<geographic<FormulaPolicy, Spheroid, CalculationType> >
+{
+ static inline geographic<FormulaPolicy, Spheroid, CalculationType>
+ apply(geographic<FormulaPolicy, Spheroid, CalculationType> const& input)
+ {
+ return input;
+ }
+};
+
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType,
+ typename P1,
+ typename P2
+>
+struct result_from_distance<geographic<FormulaPolicy, Spheroid, CalculationType>, P1, P2>
+{
+ template <typename T>
+ static inline typename return_type<geographic<FormulaPolicy, Spheroid, CalculationType>, P1, P2>::type
+ apply(geographic<FormulaPolicy, Spheroid, CalculationType> const& , T const& value)
+ {
+ return value;
+ }
+};
+
+
+template <typename Point1, typename Point2>
+struct default_strategy<point_tag, point_tag, Point1, Point2, geographic_tag, geographic_tag>
+{
+ typedef strategy::distance::geographic
+ <
+ strategy::andoyer,
+ srs::spheroid
+ <
+ typename select_coordinate_type<Point1, Point2>::type
+ >
+ > type;
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::distance
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_HPP
diff --git a/boost/geometry/strategies/geographic/distance_andoyer.hpp b/boost/geometry/strategies/geographic/distance_andoyer.hpp
index 1946cd1090..d732951642 100644
--- a/boost/geometry/strategies/geographic/distance_andoyer.hpp
+++ b/boost/geometry/strategies/geographic/distance_andoyer.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2016.
-// Modifications copyright (c) 2014-2016 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
@@ -11,24 +11,12 @@
// 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_ANDOYER_HPP
-#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_DETAIL_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_DETAIL_HPP
-#include <boost/geometry/core/coordinate_type.hpp>
-#include <boost/geometry/core/radian_access.hpp>
-#include <boost/geometry/core/radius.hpp>
-#include <boost/geometry/core/srs.hpp>
-
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
-#include <boost/geometry/formulas/andoyer_inverse.hpp>
-
-#include <boost/geometry/strategies/distance.hpp>
-
-#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
-#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/strategies/geographic/distance.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
namespace boost { namespace geometry
@@ -57,55 +45,28 @@ are about the same as Vincenty. In my (Barend's) testcases the results didn't di
*/
template
<
- typename Spheroid,
+ typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class andoyer
+ : public strategy::distance::geographic
+ <
+ strategy::andoyer, Spheroid, CalculationType
+ >
{
-public :
- template <typename Point1, typename Point2>
- struct calculation_type
- : promote_floating_point
- <
- typename select_calculation_type
- <
- Point1,
- Point2,
- CalculationType
- >::type
- >
- {};
-
- typedef Spheroid model_type;
+ typedef strategy::distance::geographic
+ <
+ strategy::andoyer, Spheroid, CalculationType
+ > base_type;
+public :
inline andoyer()
- : m_spheroid()
+ : base_type()
{}
explicit inline andoyer(Spheroid const& spheroid)
- : m_spheroid(spheroid)
+ : base_type(spheroid)
{}
-
- template <typename Point1, typename Point2>
- inline typename calculation_type<Point1, Point2>::type
- apply(Point1 const& point1, Point2 const& point2) const
- {
- return geometry::formula::andoyer_inverse
- <
- typename calculation_type<Point1, Point2>::type,
- true, false
- >::apply(get_as_radian<0>(point1), get_as_radian<1>(point1),
- get_as_radian<0>(point2), get_as_radian<1>(point2),
- m_spheroid).distance;
- }
-
- inline Spheroid const& model() const
- {
- return m_spheroid;
- }
-
-private :
- Spheroid m_spheroid;
};
@@ -154,19 +115,6 @@ struct result_from_distance<andoyer<Spheroid, CalculationType>, P1, P2>
};
-template <typename Point1, typename Point2>
-struct default_strategy<point_tag, point_tag, Point1, Point2, geographic_tag, geographic_tag>
-{
- typedef strategy::distance::andoyer
- <
- srs::spheroid
- <
- typename select_coordinate_type<Point1, Point2>::type
- >
- > type;
-};
-
-
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
@@ -177,4 +125,4 @@ struct default_strategy<point_tag, point_tag, Point1, Point2, geographic_tag, ge
}} // namespace boost::geometry
-#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_DETAIL_HPP
diff --git a/boost/geometry/strategies/geographic/distance_thomas.hpp b/boost/geometry/strategies/geographic/distance_thomas.hpp
index 39e0ecfa6f..490920c778 100644
--- a/boost/geometry/strategies/geographic/distance_thomas.hpp
+++ b/boost/geometry/strategies/geographic/distance_thomas.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015, 2016.
-// Modifications copyright (c) 2015-2016 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
@@ -15,15 +15,9 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_THOMAS_HPP
-#include <boost/geometry/core/coordinate_type.hpp>
-#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/strategies/geographic/distance.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
-#include <boost/geometry/strategies/distance.hpp>
-
-#include <boost/geometry/util/promote_floating_point.hpp>
-#include <boost/geometry/util/select_calculation_type.hpp>
-
-#include <boost/geometry/formulas/thomas_inverse.hpp>
namespace boost { namespace geometry
{
@@ -45,57 +39,28 @@ namespace strategy { namespace distance
*/
template
<
- typename Spheroid,
+ typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class thomas
+ : public strategy::distance::geographic
+ <
+ strategy::thomas, Spheroid, CalculationType
+ >
{
-public :
- template <typename Point1, typename Point2>
- struct calculation_type
- : promote_floating_point
- <
- typename select_calculation_type
- <
- Point1,
- Point2,
- CalculationType
- >::type
- >
- {};
-
- typedef Spheroid model_type;
+ typedef strategy::distance::geographic
+ <
+ strategy::thomas, Spheroid, CalculationType
+ > base_type;
+public :
inline thomas()
- : m_spheroid()
+ : base_type()
{}
explicit inline thomas(Spheroid const& spheroid)
- : m_spheroid(spheroid)
+ : base_type(spheroid)
{}
-
- template <typename Point1, typename Point2>
- inline typename calculation_type<Point1, Point2>::type
- apply(Point1 const& point1, Point2 const& point2) const
- {
- return geometry::formula::thomas_inverse
- <
- typename calculation_type<Point1, Point2>::type,
- true, false
- >::apply(get_as_radian<0>(point1),
- get_as_radian<1>(point1),
- get_as_radian<0>(point2),
- get_as_radian<1>(point2),
- m_spheroid).distance;
- }
-
- inline Spheroid const& model() const
- {
- return m_spheroid;
- }
-
-private :
- Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
diff --git a/boost/geometry/strategies/geographic/distance_vincenty.hpp b/boost/geometry/strategies/geographic/distance_vincenty.hpp
index e79e9aeb46..41146db9ff 100644
--- a/boost/geometry/strategies/geographic/distance_vincenty.hpp
+++ b/boost/geometry/strategies/geographic/distance_vincenty.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2016.
-// Modifications copyright (c) 2014-2016 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
@@ -15,15 +15,9 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_VINCENTY_HPP
-#include <boost/geometry/core/coordinate_type.hpp>
-#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/strategies/geographic/distance.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
-#include <boost/geometry/strategies/distance.hpp>
-
-#include <boost/geometry/util/promote_floating_point.hpp>
-#include <boost/geometry/util/select_calculation_type.hpp>
-
-#include <boost/geometry/formulas/vincenty_inverse.hpp>
namespace boost { namespace geometry
{
@@ -47,57 +41,28 @@ namespace strategy { namespace distance
*/
template
<
- typename Spheroid,
+ typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class vincenty
+ : public strategy::distance::geographic
+ <
+ strategy::vincenty, Spheroid, CalculationType
+ >
{
-public :
- template <typename Point1, typename Point2>
- struct calculation_type
- : promote_floating_point
- <
- typename select_calculation_type
- <
- Point1,
- Point2,
- CalculationType
- >::type
- >
- {};
-
- typedef Spheroid model_type;
+ typedef strategy::distance::geographic
+ <
+ strategy::vincenty, Spheroid, CalculationType
+ > base_type;
+public:
inline vincenty()
- : m_spheroid()
+ : base_type()
{}
explicit inline vincenty(Spheroid const& spheroid)
- : m_spheroid(spheroid)
+ : base_type(spheroid)
{}
-
- template <typename Point1, typename Point2>
- inline typename calculation_type<Point1, Point2>::type
- apply(Point1 const& point1, Point2 const& point2) const
- {
- return geometry::formula::vincenty_inverse
- <
- typename calculation_type<Point1, Point2>::type,
- true, false
- >::apply(get_as_radian<0>(point1),
- get_as_radian<1>(point1),
- get_as_radian<0>(point2),
- get_as_radian<1>(point2),
- m_spheroid).distance;
- }
-
- inline Spheroid const& model() const
- {
- return m_spheroid;
- }
-
-private :
- Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
diff --git a/boost/geometry/strategies/geographic/envelope_segment.hpp b/boost/geometry/strategies/geographic/envelope_segment.hpp
new file mode 100644
index 0000000000..3641b39428
--- /dev/null
+++ b/boost/geometry/strategies/geographic/envelope_segment.hpp
@@ -0,0 +1,104 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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_ENVELOPE_SEGMENT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ENVELOPE_SEGMENT_HPP
+
+
+#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
+#include <boost/geometry/algorithms/detail/normalize.hpp>
+#include <boost/geometry/core/srs.hpp>
+#include <boost/geometry/strategies/envelope.hpp>
+#include <boost/geometry/strategies/geographic/azimuth.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace envelope
+{
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = geometry::srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic_segment
+{
+public:
+ typedef Spheroid model_type;
+
+ inline geographic_segment()
+ : m_spheroid()
+ {}
+
+ explicit inline geographic_segment(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {}
+
+ template <typename Point1, typename Point2, typename Box>
+ inline void apply(Point1 const& point1, Point2 const& point2, Box& box) const
+ {
+ Point1 p1_normalized = detail::return_normalized<Point1>(point1);
+ Point2 p2_normalized = detail::return_normalized<Point2>(point2);
+
+ geometry::strategy::azimuth::geographic
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType
+ > azimuth_geographic(m_spheroid);
+
+ typedef typename coordinate_system<Point1>::type::units units_type;
+
+ detail::envelope::envelope_segment_impl
+ <
+ geographic_tag
+ >::template apply<units_type>(geometry::get<0>(p1_normalized),
+ geometry::get<1>(p1_normalized),
+ geometry::get<0>(p2_normalized),
+ geometry::get<1>(p2_normalized),
+ box,
+ azimuth_geographic);
+
+ }
+
+private:
+ Spheroid m_spheroid;
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<geographic_tag, CalculationType>
+{
+ typedef strategy::envelope::geographic_segment
+ <
+ strategy::andoyer,
+ srs::spheroid<double>,
+ CalculationType
+ > type;
+};
+
+}
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::envelope
+
+}} //namepsace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ENVELOPE_SEGMENT_HPP
diff --git a/boost/geometry/strategies/geographic/intersection.hpp b/boost/geometry/strategies/geographic/intersection.hpp
new file mode 100644
index 0000000000..1708c274c0
--- /dev/null
+++ b/boost/geometry/strategies/geographic/intersection.hpp
@@ -0,0 +1,897 @@
+// Boost.Geometry
+
+// Copyright (c) 2016-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_STRATEGIES_GEOGRAPHIC_INTERSECTION_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_HPP
+
+#include <algorithm>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/srs.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/algorithms/detail/assign_values.hpp>
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+#include <boost/geometry/algorithms/detail/recalculate.hpp>
+
+#include <boost/geometry/formulas/andoyer_inverse.hpp>
+#include <boost/geometry/formulas/sjoberg_intersection.hpp>
+#include <boost/geometry/formulas/spherical.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/geometries/concepts/segment_concept.hpp>
+
+#include <boost/geometry/policies/robustness/segment_ratio.hpp>
+
+#include <boost/geometry/strategies/geographic/area.hpp>
+#include <boost/geometry/strategies/geographic/distance.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+#include <boost/geometry/strategies/geographic/side.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/intersection_result.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace intersection
+{
+
+// CONSIDER: Improvement of the robustness/accuracy/repeatability by
+// moving all segments to 0 longitude
+// picking latitudes closer to 0
+// etc.
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ unsigned int Order = strategy::default_order<FormulaPolicy>::value,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+struct geographic_segments
+{
+ typedef side::geographic
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ > side_strategy_type;
+
+ inline side_strategy_type get_side_strategy() const
+ {
+ return side_strategy_type(m_spheroid);
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ struct point_in_geometry_strategy
+ {
+ typedef strategy::within::winding
+ <
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type,
+ side_strategy_type,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry1, typename Geometry2>
+ inline typename point_in_geometry_strategy<Geometry1, Geometry2>::type
+ get_point_in_geometry_strategy() const
+ {
+ typedef typename point_in_geometry_strategy
+ <
+ Geometry1, Geometry2
+ >::type strategy_type;
+ return strategy_type(get_side_strategy());
+ }
+
+ template <typename Geometry>
+ struct area_strategy
+ {
+ typedef area::geographic
+ <
+ typename point_type<Geometry>::type,
+ FormulaPolicy,
+ Order,
+ Spheroid,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry>
+ inline typename area_strategy<Geometry>::type get_area_strategy() const
+ {
+ typedef typename area_strategy<Geometry>::type strategy_type;
+ return strategy_type(m_spheroid);
+ }
+
+ template <typename Geometry>
+ struct distance_strategy
+ {
+ typedef distance::geographic
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry>
+ inline typename distance_strategy<Geometry>::type get_distance_strategy() const
+ {
+ typedef typename distance_strategy<Geometry>::type strategy_type;
+ return 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>
+ struct segment_intersection_info
+ {
+ typedef typename select_most_precise
+ <
+ CoordinateType, double
+ >::type promoted_type;
+
+ promoted_type comparable_length_a() const
+ {
+ return robust_ra.denominator();
+ }
+
+ promoted_type comparable_length_b() const
+ {
+ return robust_rb.denominator();
+ }
+
+ template <typename Point, typename Segment1, typename Segment2>
+ void assign_a(Point& point, Segment1 const& a, Segment2 const& b) const
+ {
+ assign(point, a, b);
+ }
+ template <typename Point, typename Segment1, typename Segment2>
+ void assign_b(Point& point, Segment1 const& a, Segment2 const& b) const
+ {
+ assign(point, a, b);
+ }
+
+ template <typename Point, typename Segment1, typename Segment2>
+ void assign(Point& point, Segment1 const& a, Segment2 const& b) const
+ {
+ if (ip_flag == ipi_inters)
+ {
+ // TODO: assign the rest of coordinates
+ set_from_radian<0>(point, lon);
+ set_from_radian<1>(point, lat);
+ }
+ else if (ip_flag == ipi_at_a1)
+ {
+ detail::assign_point_from_index<0>(a, point);
+ }
+ else if (ip_flag == ipi_at_a2)
+ {
+ detail::assign_point_from_index<1>(a, point);
+ }
+ else if (ip_flag == ipi_at_b1)
+ {
+ detail::assign_point_from_index<0>(b, point);
+ }
+ else // ip_flag == ipi_at_b2
+ {
+ detail::assign_point_from_index<1>(b, point);
+ }
+ }
+
+ CoordinateType lon;
+ CoordinateType lat;
+ SegmentRatio robust_ra;
+ SegmentRatio robust_rb;
+ intersection_point_flag ip_flag;
+ };
+
+ explicit geographic_segments(Spheroid const& spheroid = Spheroid())
+ : m_spheroid(spheroid)
+ {}
+
+ // Relate segments a and b
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename Policy,
+ typename RobustPolicy
+ >
+ inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
+ Policy const& policy,
+ RobustPolicy const& robust_policy) const
+ {
+ typedef typename point_type<Segment1>::type point1_t;
+ typedef typename point_type<Segment2>::type point2_t;
+ point1_t a1, a2;
+ point2_t b1, b2;
+
+ detail::assign_point_from_index<0>(a, a1);
+ detail::assign_point_from_index<1>(a, a2);
+ detail::assign_point_from_index<0>(b, b1);
+ detail::assign_point_from_index<1>(b, b2);
+
+ return apply(a, b, policy, robust_policy, a1, a2, b1, b2);
+ }
+
+ // Relate segments a and b
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename Policy,
+ typename RobustPolicy,
+ typename Point1,
+ typename Point2
+ >
+ inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
+ Policy const&, RobustPolicy const&,
+ Point1 a1, Point1 a2, Point2 b1, Point2 b2) const
+ {
+ bool is_a_reversed = get<1>(a1) > get<1>(a2);
+ bool is_b_reversed = get<1>(b1) > get<1>(b2);
+
+ if (is_a_reversed)
+ {
+ std::swap(a1, a2);
+ }
+
+ if (is_b_reversed)
+ {
+ std::swap(b1, b2);
+ }
+
+ return apply<Policy>(a, b, a1, a2, b1, b2, is_a_reversed, is_b_reversed);
+ }
+
+private:
+ // Relate segments a and b
+ template
+ <
+ typename Policy,
+ typename Segment1,
+ typename Segment2,
+ typename Point1,
+ typename Point2
+ >
+ inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
+ Point1 const& a1, Point1 const& a2,
+ Point2 const& b1, Point2 const& b2,
+ bool is_a_reversed, bool is_b_reversed) const
+ {
+ BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );
+ BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
+
+ typedef typename select_calculation_type
+ <Segment1, Segment2, CalculationType>::type calc_t;
+
+ // normalized spheroid
+ srs::spheroid<calc_t> spheroid = normalized_spheroid<calc_t>(m_spheroid);
+
+ // TODO: check only 2 first coordinates here?
+ using geometry::detail::equals::equals_point_point;
+ bool a_is_point = equals_point_point(a1, a2);
+ bool b_is_point = equals_point_point(b1, b2);
+
+ if(a_is_point && b_is_point)
+ {
+ return equals_point_point(a1, b2)
+ ? Policy::degenerate(a, true)
+ : Policy::disjoint()
+ ;
+ }
+
+ calc_t const a1_lon = get_as_radian<0>(a1);
+ calc_t const a1_lat = get_as_radian<1>(a1);
+ calc_t const a2_lon = get_as_radian<0>(a2);
+ calc_t const a2_lat = get_as_radian<1>(a2);
+ calc_t const b1_lon = get_as_radian<0>(b1);
+ calc_t const b1_lat = get_as_radian<1>(b1);
+ calc_t const b2_lon = get_as_radian<0>(b2);
+ calc_t const b2_lat = get_as_radian<1>(b2);
+
+ side_info sides;
+
+ // NOTE: potential optimization, don't calculate distance at this point
+ // this would require to reimplement inverse strategy to allow
+ // calculation of distance if needed, probably also storing intermediate
+ // results somehow inside an object.
+ typedef typename FormulaPolicy::template inverse<calc_t, true, true, false, false, false> inverse_dist_azi;
+ typedef typename inverse_dist_azi::result_type inverse_result;
+
+ // 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);
+
+ 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>())
+ {
+ // 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);
+
+ 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>())
+ {
+ // Both points are at the same side of other segment, we can leave
+ return Policy::disjoint();
+ }
+
+ // NOTE: at this point the segments may still be disjoint
+ // NOTE: at this point one of the segments may be degenerated
+
+ bool collinear = sides.collinear();
+
+ if (! collinear)
+ {
+ // WARNING: the side strategy doesn't have the info about the other
+ // segment so it may return results inconsistent with this intersection
+ // strategy, as it checks both segments for consistency
+
+ if (sides.get<0, 0>() == 0 && sides.get<0, 1>() == 0)
+ {
+ collinear = true;
+ sides.set<1>(0, 0);
+ }
+ else if (sides.get<1, 0>() == 0 && sides.get<1, 1>() == 0)
+ {
+ collinear = true;
+ sides.set<0>(0, 0);
+ }
+ }
+
+ if (collinear)
+ {
+ 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);
+ }
+ 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);
+ }
+ else
+ {
+ calc_t dist_a1_a2, dist_a1_b1, dist_a1_b2;
+ calc_t dist_b1_b2, dist_b1_a1, dist_b1_a2;
+ // 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);
+ 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);
+ dist_a1_a2 = dist_b1_a2 - dist_b1_a1;
+ dist_a1_b1 = -dist_b1_a1;
+ dist_a1_b2 = dist_b1_b2 - dist_b1_a1;
+ }
+
+ // NOTE: this is probably not needed
+ calc_t const c0 = 0;
+ int a1_on_b = position_value(c0, dist_a1_b1, dist_a1_b2);
+ int a2_on_b = position_value(dist_a1_a2, dist_a1_b1, dist_a1_b2);
+ int b1_on_a = position_value(c0, dist_b1_a1, dist_b1_a2);
+ int b2_on_a = position_value(dist_b1_b2, dist_b1_a1, dist_b1_a2);
+
+ if ((a1_on_b < 1 && a2_on_b < 1) || (a1_on_b > 3 && a2_on_b > 3))
+ {
+ return Policy::disjoint();
+ }
+
+ if (a1_on_b == 1)
+ {
+ dist_b1_a1 = 0;
+ dist_a1_b1 = 0;
+ }
+ else if (a1_on_b == 3)
+ {
+ dist_b1_a1 = dist_b1_b2;
+ dist_a1_b2 = 0;
+ }
+
+ if (a2_on_b == 1)
+ {
+ dist_b1_a2 = 0;
+ dist_a1_b1 = dist_a1_a2;
+ }
+ else if (a2_on_b == 3)
+ {
+ dist_b1_a2 = dist_b1_b2;
+ dist_a1_b2 = dist_a1_a2;
+ }
+
+ bool opposite = ! same_direction(res_a1_a2.azimuth, res_b1_b2.azimuth);
+
+ // NOTE: If segment was reversed opposite, positions and segment ratios has to be altered
+ if (is_a_reversed)
+ {
+ // opposite
+ opposite = ! opposite;
+ // positions
+ std::swap(a1_on_b, a2_on_b);
+ b1_on_a = 4 - b1_on_a;
+ b2_on_a = 4 - b2_on_a;
+ // distances for ratios
+ std::swap(dist_b1_a1, dist_b1_a2);
+ dist_a1_b1 = dist_a1_a2 - dist_a1_b1;
+ dist_a1_b2 = dist_a1_a2 - dist_a1_b2;
+ }
+ if (is_b_reversed)
+ {
+ // opposite
+ opposite = ! opposite;
+ // positions
+ a1_on_b = 4 - a1_on_b;
+ a2_on_b = 4 - a2_on_b;
+ std::swap(b1_on_a, b2_on_a);
+ // distances for ratios
+ dist_b1_a1 = dist_b1_b2 - dist_b1_a1;
+ dist_b1_a2 = dist_b1_b2 - dist_b1_a2;
+ std::swap(dist_a1_b1, dist_a1_b2);
+ }
+
+ segment_ratio<calc_t> ra_from(dist_b1_a1, dist_b1_b2);
+ segment_ratio<calc_t> ra_to(dist_b1_a2, dist_b1_b2);
+ segment_ratio<calc_t> rb_from(dist_a1_b1, dist_a1_a2);
+ segment_ratio<calc_t> rb_to(dist_a1_b2, dist_a1_a2);
+
+ return Policy::segments_collinear(a, b, opposite,
+ a1_on_b, a2_on_b, b1_on_a, b2_on_a,
+ ra_from, ra_to, rb_from, rb_to);
+ }
+ }
+ else // crossing or touching
+ {
+ if (a_is_point || b_is_point)
+ {
+ return Policy::disjoint();
+ }
+
+ calc_t lon = 0, lat = 0;
+ intersection_point_flag ip_flag;
+ calc_t dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1;
+ if (calculate_ip_data(a1, a2, b1, b2,
+ a1_lon, a1_lat, a2_lon, a2_lat,
+ b1_lon, b1_lat, b2_lon, b2_lat,
+ res_a1_a2, res_a1_b1, res_a1_b2,
+ res_b1_b2, res_b1_a1, res_b1_a2,
+ sides, spheroid,
+ lon, lat,
+ dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1,
+ ip_flag))
+ {
+ // NOTE: If segment was reversed sides and segment ratios has to be altered
+ if (is_a_reversed)
+ {
+ // sides
+ sides_reverse_segment<0>(sides);
+ // distance for ratio
+ dist_a1_i1 = dist_a1_a2 - dist_a1_i1;
+ // ip flag
+ ip_flag_reverse_segment(ip_flag, ipi_at_a1, ipi_at_a2);
+ }
+ if (is_b_reversed)
+ {
+ // sides
+ sides_reverse_segment<1>(sides);
+ // distance for ratio
+ dist_b1_i1 = dist_b1_b2 - dist_b1_i1;
+ // ip flag
+ ip_flag_reverse_segment(ip_flag, ipi_at_b1, ipi_at_b2);
+ }
+
+ // intersects
+ segment_intersection_info
+ <
+ calc_t,
+ segment_ratio<calc_t>
+ > sinfo;
+
+ sinfo.lon = lon;
+ sinfo.lat = lat;
+ sinfo.robust_ra.assign(dist_a1_i1, dist_a1_a2);
+ sinfo.robust_rb.assign(dist_b1_i1, dist_b1_b2);
+ sinfo.ip_flag = ip_flag;
+
+ return Policy::segments_crosses(sides, sinfo, a, b);
+ }
+ else
+ {
+ return Policy::disjoint();
+ }
+ }
+ }
+
+ template <typename Policy, typename CalcT, typename Segment, typename Point1, typename Point2, typename ResultInverse>
+ static inline typename Policy::return_type
+ collinear_one_degenerated(Segment const& segment, bool degenerated_a,
+ 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)
+ {
+ 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))
+ {
+ return Policy::disjoint();
+ }
+
+ // NOTE: If segment was reversed segment ratio has to be altered
+ if (is_other_reversed)
+ {
+ // distance for ratio
+ dist_1_o = dist_1_2 - dist_1_o;
+ }
+
+ return Policy::one_degenerate(segment, segment_ratio<CalcT>(dist_1_o, dist_1_2), degenerated_a);
+ }
+
+ // TODO: instead of checks below test bi against a1 and a2 here?
+ // in order to make this independent from is_near()
+ template <typename Point1, typename Point2, typename ResultInverse, typename CalcT>
+ 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
+ {
+ 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 = -dist_a1_bi;
+ }
+
+ // if i1 is close to a1 and b1 or b2 is equal to a1
+ if (is_endpoint_equal(dist_a1_bi, a1, b1, b2))
+ {
+ dist_a1_bi = 0;
+ return true;
+ }
+ // or i1 is close to a2 and b1 or b2 is equal to a2
+ else if (is_endpoint_equal(dist_a1_a2 - dist_a1_bi, a2, b1, b2))
+ {
+ 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();
+ }
+
+ template <typename Point1, typename Point2, typename CalcT, typename ResultInverse, typename Spheroid_>
+ static inline bool calculate_ip_data(Point1 const& a1, Point1 const& a2, // in
+ Point2 const& b1, Point2 const& b2, // in
+ CalcT const& a1_lon, CalcT const& a1_lat, // in
+ CalcT const& a2_lon, CalcT const& a2_lat, // in
+ CalcT const& b1_lon, CalcT const& b1_lat, // in
+ CalcT const& b2_lon, CalcT const& b2_lat, // in
+ ResultInverse const& res_a1_a2, // in
+ ResultInverse const& res_a1_b1, // in
+ ResultInverse const& res_a1_b2, // in
+ ResultInverse const& res_b1_b2, // in
+ ResultInverse const& res_b1_a1, // in
+ ResultInverse const& res_b1_a2, // in
+ side_info const& sides, // in
+ Spheroid_ const& spheroid, // in
+ CalcT & lon, CalcT & lat, // 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
+ {
+ dist_a1_a2 = res_a1_a2.distance;
+ dist_b1_b2 = res_b1_b2.distance;
+
+ // assign the IP if some endpoints overlap
+ using geometry::detail::equals::equals_point_point;
+ if (equals_point_point(a1, b1))
+ {
+ lon = a1_lon;
+ lat = a1_lat;
+ dist_a1_ip = 0;
+ dist_b1_ip = 0;
+ ip_flag = ipi_at_a1;
+ return true;
+ }
+ else if (equals_point_point(a1, b2))
+ {
+ lon = a1_lon;
+ lat = a1_lat;
+ dist_a1_ip = 0;
+ dist_b1_ip = dist_b1_b2;
+ ip_flag = ipi_at_a1;
+ return true;
+ }
+ else if (equals_point_point(a2, b1))
+ {
+ lon = a2_lon;
+ lat = a2_lat;
+ dist_a1_ip = dist_a1_a2;
+ dist_b1_ip = 0;
+ ip_flag = ipi_at_a2;
+ return true;
+ }
+ else if (equals_point_point(a2, b2))
+ {
+ lon = a2_lon;
+ lat = a2_lat;
+ dist_a1_ip = dist_a1_a2;
+ dist_b1_ip = dist_b1_b2;
+ ip_flag = ipi_at_a2;
+ return true;
+ }
+
+ // at this point we know that the endpoints doesn't overlap
+ // check cases when an endpoint lies on the other geodesic
+ if (sides.template get<0, 0>() == 0) // a1 wrt b
+ {
+ if (res_b1_a1.distance <= res_b1_b2.distance
+ && same_direction(res_b1_a1.azimuth, res_b1_b2.azimuth))
+ {
+ lon = a1_lon;
+ lat = a1_lat;
+ dist_a1_ip = 0;
+ dist_b1_ip = res_b1_a1.distance;
+ ip_flag = ipi_at_a1;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (sides.template get<0, 1>() == 0) // a2 wrt b
+ {
+ if (res_b1_a2.distance <= res_b1_b2.distance
+ && same_direction(res_b1_a2.azimuth, res_b1_b2.azimuth))
+ {
+ lon = a2_lon;
+ lat = a2_lat;
+ dist_a1_ip = res_a1_a2.distance;
+ dist_b1_ip = res_b1_a2.distance;
+ ip_flag = ipi_at_a2;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (sides.template get<1, 0>() == 0) // b1 wrt a
+ {
+ if (res_a1_b1.distance <= res_a1_a2.distance
+ && same_direction(res_a1_b1.azimuth, res_a1_a2.azimuth))
+ {
+ lon = b1_lon;
+ lat = b1_lat;
+ dist_a1_ip = res_a1_b1.distance;
+ dist_b1_ip = 0;
+ ip_flag = ipi_at_b1;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (sides.template get<1, 1>() == 0) // b2 wrt a
+ {
+ if (res_a1_b2.distance <= res_a1_a2.distance
+ && same_direction(res_a1_b2.azimuth, res_a1_a2.azimuth))
+ {
+ lon = b2_lon;
+ lat = b2_lat;
+ dist_a1_ip = res_a1_b2.distance;
+ dist_b1_ip = res_b1_b2.distance;
+ ip_flag = ipi_at_b2;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // At this point neither the endpoints overlaps
+ // nor any andpoint lies on the other geodesic
+ // So the endpoints should lie on the opposite sides of both geodesics
+
+ bool const ok = formula::sjoberg_intersection<CalcT, FormulaPolicy::template inverse, Order>
+ ::apply(a1_lon, a1_lat, a2_lon, a2_lat, res_a1_a2.azimuth,
+ b1_lon, b1_lat, b2_lon, b2_lat, res_b1_b2.azimuth,
+ lon, lat, spheroid);
+
+ if (! ok)
+ {
+ return false;
+ }
+
+ typedef typename FormulaPolicy::template inverse<CalcT, true, true, false, false, false> inverse_dist_azi;
+ typedef typename inverse_dist_azi::result_type inverse_result;
+
+ inverse_result const res_a1_ip = inverse_dist_azi::apply(a1_lon, a1_lat, lon, lat, spheroid);
+ dist_a1_ip = res_a1_ip.distance;
+ if (! same_direction(res_a1_ip.azimuth, res_a1_a2.azimuth))
+ {
+ dist_a1_ip = -dist_a1_ip;
+ }
+
+ bool is_on_a = segment_ratio<CalcT>(dist_a1_ip, dist_a1_a2).on_segment();
+ // NOTE: not fully consistent with equals_point_point() since radians are always used.
+ bool is_on_a1 = math::equals(lon, a1_lon) && math::equals(lat, a1_lat);
+ bool is_on_a2 = math::equals(lon, a2_lon) && math::equals(lat, a2_lat);
+
+ if (! (is_on_a || is_on_a1 || is_on_a2))
+ {
+ return false;
+ }
+
+ inverse_result const res_b1_ip = inverse_dist_azi::apply(b1_lon, b1_lat, lon, lat, spheroid);
+ dist_b1_ip = res_b1_ip.distance;
+ if (! same_direction(res_b1_ip.azimuth, res_b1_b2.azimuth))
+ {
+ dist_b1_ip = -dist_b1_ip;
+ }
+
+ bool is_on_b = segment_ratio<CalcT>(dist_b1_ip, dist_b1_b2).on_segment();
+ // NOTE: not fully consistent with equals_point_point() since radians are always used.
+ bool is_on_b1 = math::equals(lon, b1_lon) && math::equals(lat, b1_lat);
+ bool is_on_b2 = math::equals(lon, b2_lon) && math::equals(lat, b2_lat);
+
+ if (! (is_on_b || is_on_b1 || is_on_b2))
+ {
+ return false;
+ }
+
+ ip_flag = ipi_inters;
+
+ if (is_on_b1)
+ {
+ lon = b1_lon;
+ lat = b1_lat;
+ dist_b1_ip = 0;
+ ip_flag = ipi_at_b1;
+ }
+ else if (is_on_b2)
+ {
+ lon = b2_lon;
+ lat = b2_lat;
+ dist_b1_ip = res_b1_b2.distance;
+ ip_flag = ipi_at_b2;
+ }
+
+ if (is_on_a1)
+ {
+ lon = a1_lon;
+ lat = a1_lat;
+ dist_a1_ip = 0;
+ ip_flag = ipi_at_a1;
+ }
+ else if (is_on_a2)
+ {
+ lon = a2_lon;
+ lat = a2_lat;
+ dist_a1_ip = res_a1_a2.distance;
+ ip_flag = ipi_at_a2;
+ }
+
+ return true;
+ }
+
+ template <typename CalcT, typename P1, typename P2>
+ static inline bool is_endpoint_equal(CalcT const& dist,
+ P1 const& ai, P2 const& b1, P2 const& b2)
+ {
+ using geometry::detail::equals::equals_point_point;
+ return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2));
+ }
+
+ template <typename CalcT>
+ static inline bool is_near(CalcT const& dist)
+ {
+ // NOTE: This strongly depends on the Inverse method
+ CalcT const small_number = CalcT(boost::is_same<CalcT, float>::value ? 0.0001 : 0.00000001);
+ return math::abs(dist) <= small_number;
+ }
+
+ template <typename ProjCoord1, typename ProjCoord2>
+ static inline int position_value(ProjCoord1 const& ca1,
+ ProjCoord2 const& cb1,
+ ProjCoord2 const& cb2)
+ {
+ // S1x 0 1 2 3 4
+ // S2 |---------->
+ return math::equals(ca1, cb1) ? 1
+ : math::equals(ca1, cb2) ? 3
+ : cb1 < cb2 ?
+ ( ca1 < cb1 ? 0
+ : ca1 > cb2 ? 4
+ : 2 )
+ : ( ca1 > cb1 ? 0
+ : ca1 < cb2 ? 4
+ : 2 );
+ }
+
+ template <typename CalcT>
+ static inline bool same_direction(CalcT const& azimuth1, CalcT const& azimuth2)
+ {
+ // distance between two angles normalized to (-180, 180]
+ CalcT const angle_diff = math::longitude_distance_signed<radian>(azimuth1, azimuth2);
+ return math::abs(angle_diff) <= math::half_pi<CalcT>();
+ }
+
+ template <int Which>
+ static inline void sides_reverse_segment(side_info & sides)
+ {
+ // names assuming segment A is reversed (Which == 0)
+ int a1_wrt_b = sides.template get<Which, 0>();
+ int a2_wrt_b = sides.template get<Which, 1>();
+ std::swap(a1_wrt_b, a2_wrt_b);
+ sides.template set<Which>(a1_wrt_b, a2_wrt_b);
+ int b1_wrt_a = sides.template get<1 - Which, 0>();
+ int b2_wrt_a = sides.template get<1 - Which, 1>();
+ sides.template set<1 - Which>(-b1_wrt_a, -b2_wrt_a);
+ }
+
+ static inline void ip_flag_reverse_segment(intersection_point_flag & ip_flag,
+ intersection_point_flag const& ipi_at_p1,
+ intersection_point_flag const& ipi_at_p2)
+ {
+ ip_flag = ip_flag == ipi_at_p1 ? ipi_at_p2 :
+ ip_flag == ipi_at_p2 ? ipi_at_p1 :
+ ip_flag;
+ }
+
+ template <typename CalcT, typename SpheroidT>
+ static inline srs::spheroid<CalcT> normalized_spheroid(SpheroidT const& spheroid)
+ {
+ return srs::spheroid<CalcT>(CalcT(1),
+ CalcT(get_radius<2>(spheroid)) // b/a
+ / CalcT(get_radius<0>(spheroid)));
+ }
+
+private:
+ Spheroid m_spheroid;
+};
+
+
+}} // namespace strategy::intersection
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_HPP
diff --git a/boost/geometry/strategies/geographic/intersection_elliptic.hpp b/boost/geometry/strategies/geographic/intersection_elliptic.hpp
new file mode 100644
index 0000000000..76e9940fe3
--- /dev/null
+++ b/boost/geometry/strategies/geographic/intersection_elliptic.hpp
@@ -0,0 +1,243 @@
+// Boost.Geometry
+
+// Copyright (c) 2016-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_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP
+
+
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/formulas/geographic.hpp>
+
+#include <boost/geometry/strategies/spherical/intersection.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace intersection
+{
+
+template <typename Spheroid>
+struct great_elliptic_segments_calc_policy
+ : spherical_segments_calc_policy
+{
+ explicit great_elliptic_segments_calc_policy(Spheroid const& spheroid = Spheroid())
+ : m_spheroid(spheroid)
+ {}
+
+ template <typename Point, typename Point3d>
+ Point from_cart3d(Point3d const& point_3d) const
+ {
+ return formula::cart3d_to_geo<Point>(point_3d, m_spheroid);
+ }
+
+ template <typename Point3d, typename Point>
+ Point3d to_cart3d(Point const& point) const
+ {
+ return formula::geo_to_cart3d<Point3d>(point, m_spheroid);
+ }
+
+ // relate_xxx_calc_policy must live londer than plane because it contains
+ // Spheroid object and plane keeps the reference to that object.
+ template <typename Point3d>
+ struct plane
+ {
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ // not normalized
+ plane(Point3d const& p1, Point3d const& p2)
+ : normal(cross_product(p1, p2))
+ {}
+
+ int side_value(Point3d const& pt) const
+ {
+ return formula::sph_side_value(normal, pt);
+ }
+
+ coord_t cos_angle_between(Point3d const& p1, Point3d const& p2) const
+ {
+ Point3d v1 = p1;
+ detail::vec_normalize(v1);
+ Point3d v2 = p2;
+ detail::vec_normalize(v2);
+
+ return dot_product(v1, v2);
+ }
+
+ coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const
+ {
+ coord_t const c0 = 0;
+
+ Point3d v1 = p1;
+ detail::vec_normalize(v1);
+ Point3d v2 = p2;
+ detail::vec_normalize(v2);
+
+ is_forward = dot_product(normal, cross_product(v1, v2)) >= c0;
+ return dot_product(v1, v2);
+ }
+
+ Point3d normal;
+ };
+
+ template <typename Point3d>
+ plane<Point3d> get_plane(Point3d const& p1, Point3d const& p2) const
+ {
+ return plane<Point3d>(p1, p2);
+ }
+
+ template <typename Point3d>
+ bool intersection_points(plane<Point3d> const& plane1,
+ plane<Point3d> const& plane2,
+ Point3d & ip1, Point3d & ip2) const
+ {
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ Point3d id = cross_product(plane1.normal, plane2.normal);
+ // NOTE: the length should be greater than 0 at this point
+ // NOTE: no need to normalize in this case
+
+ ip1 = formula::projected_to_surface(id, m_spheroid);
+
+ ip2 = ip1;
+ multiply_value(ip2, coord_t(-1));
+
+ return true;
+ }
+
+private:
+ Spheroid m_spheroid;
+};
+
+template <typename Spheroid>
+struct experimental_elliptic_segments_calc_policy
+{
+ explicit experimental_elliptic_segments_calc_policy(Spheroid const& spheroid = Spheroid())
+ : m_spheroid(spheroid)
+ {}
+
+ template <typename Point, typename Point3d>
+ Point from_cart3d(Point3d const& point_3d) const
+ {
+ return formula::cart3d_to_geo<Point>(point_3d, m_spheroid);
+ }
+
+ template <typename Point3d, typename Point>
+ Point3d to_cart3d(Point const& point) const
+ {
+ return formula::geo_to_cart3d<Point3d>(point, m_spheroid);
+ }
+
+ // relate_xxx_calc_policy must live londer than plane because it contains
+ // Spheroid object and plane keeps the reference to that object.
+ template <typename Point3d>
+ struct plane
+ {
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ // not normalized
+ plane(Point3d const& p1, Point3d const& p2, Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {
+ formula::experimental_elliptic_plane(p1, p2, origin, normal, m_spheroid);
+ }
+
+ int side_value(Point3d const& pt) const
+ {
+ return formula::elliptic_side_value(origin, normal, pt);
+ }
+
+ coord_t cos_angle_between(Point3d const& p1, Point3d const& p2) const
+ {
+ Point3d const v1 = normalized_vec(p1);
+ Point3d const v2 = normalized_vec(p2);
+ return dot_product(v1, v2);
+ }
+
+ coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const
+ {
+ coord_t const c0 = 0;
+
+ Point3d const v1 = normalized_vec(p1);
+ Point3d const v2 = normalized_vec(p2);
+
+ is_forward = dot_product(normal, cross_product(v1, v2)) >= c0;
+ return dot_product(v1, v2);
+ }
+
+ Point3d origin;
+ Point3d normal;
+
+ private:
+ Point3d normalized_vec(Point3d const& p) const
+ {
+ Point3d v = p;
+ subtract_point(v, origin);
+ detail::vec_normalize(v);
+ return v;
+ }
+
+ Spheroid const& m_spheroid;
+ };
+
+ template <typename Point3d>
+ plane<Point3d> get_plane(Point3d const& p1, Point3d const& p2) const
+ {
+ return plane<Point3d>(p1, p2, m_spheroid);
+ }
+
+ template <typename Point3d>
+ bool intersection_points(plane<Point3d> const& plane1,
+ plane<Point3d> const& plane2,
+ Point3d & ip1, Point3d & ip2) const
+ {
+ return formula::planes_spheroid_intersection(plane1.origin, plane1.normal,
+ plane2.origin, plane2.normal,
+ ip1, ip2, m_spheroid);
+ }
+
+private:
+ Spheroid m_spheroid;
+};
+
+
+template
+<
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+struct great_elliptic_segments
+ : ecef_segments
+ <
+ great_elliptic_segments_calc_policy<Spheroid>,
+ CalculationType
+ >
+{};
+
+template
+<
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+struct experimental_elliptic_segments
+ : ecef_segments
+ <
+ experimental_elliptic_segments_calc_policy<Spheroid>,
+ CalculationType
+ >
+{};
+
+
+}} // namespace strategy::intersection
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP
diff --git a/boost/geometry/strategies/geographic/mapping_ssf.hpp b/boost/geometry/strategies/geographic/mapping_ssf.hpp
index 3beedc7809..20a0523616 100644
--- a/boost/geometry/strategies/geographic/mapping_ssf.hpp
+++ b/boost/geometry/strategies/geographic/mapping_ssf.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2011-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
@@ -136,7 +136,7 @@ public :
{}
template <typename P1, typename P2, typename P>
- inline int apply(P1 const& p1, P2 const& p2, P const& p)
+ inline int apply(P1 const& p1, P2 const& p2, P const& p) const
{
typedef typename promote_floating_point
<
diff --git a/boost/geometry/strategies/geographic/parameters.hpp b/boost/geometry/strategies/geographic/parameters.hpp
new file mode 100644
index 0000000000..5638db50fa
--- /dev/null
+++ b/boost/geometry/strategies/geographic/parameters.hpp
@@ -0,0 +1,117 @@
+// 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_STRATEGIES_GEOGRAPHIC_PARAMETERS_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_PARAMETERS_HPP
+
+
+#include <boost/geometry/formulas/andoyer_inverse.hpp>
+#include <boost/geometry/formulas/thomas_inverse.hpp>
+#include <boost/geometry/formulas/vincenty_inverse.hpp>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/integral_c.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy
+{
+
+struct andoyer
+{
+ template
+ <
+ typename CT,
+ bool EnableDistance,
+ bool EnableAzimuth,
+ bool EnableReverseAzimuth = false,
+ bool EnableReducedLength = false,
+ bool EnableGeodesicScale = false
+ >
+ struct inverse
+ : formula::andoyer_inverse
+ <
+ CT, EnableDistance,
+ EnableAzimuth, EnableReverseAzimuth,
+ EnableReducedLength, EnableGeodesicScale
+ >
+ {};
+};
+
+struct thomas
+{
+ template
+ <
+ typename CT,
+ bool EnableDistance,
+ bool EnableAzimuth,
+ bool EnableReverseAzimuth = false,
+ bool EnableReducedLength = false,
+ bool EnableGeodesicScale = false
+ >
+ struct inverse
+ : formula::thomas_inverse
+ <
+ CT, EnableDistance,
+ EnableAzimuth, EnableReverseAzimuth,
+ EnableReducedLength, EnableGeodesicScale
+ >
+ {};
+};
+
+struct vincenty
+{
+ template
+ <
+ typename CT,
+ bool EnableDistance,
+ bool EnableAzimuth,
+ bool EnableReverseAzimuth = false,
+ bool EnableReducedLength = false,
+ bool EnableGeodesicScale = false
+ >
+ struct inverse
+ : formula::vincenty_inverse
+ <
+ CT, EnableDistance,
+ EnableAzimuth, EnableReverseAzimuth,
+ EnableReducedLength, EnableGeodesicScale
+ >
+ {};
+};
+
+
+template <typename FormulaPolicy>
+struct default_order
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_TYPE
+ , (types<FormulaPolicy>)
+ );
+};
+
+template<>
+struct default_order<andoyer>
+ : boost::mpl::integral_c<unsigned int, 1>
+{};
+
+template<>
+struct default_order<thomas>
+ : boost::mpl::integral_c<unsigned int, 2>
+{};
+
+template<>
+struct default_order<vincenty>
+ : boost::mpl::integral_c<unsigned int, 4>
+{};
+
+}}} // namespace boost::geometry::strategy
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_PARAMETERS_HPP
diff --git a/boost/geometry/strategies/geographic/side.hpp b/boost/geometry/strategies/geographic/side.hpp
new file mode 100644
index 0000000000..0d40e4da20
--- /dev/null
+++ b/boost/geometry/strategies/geographic/side.hpp
@@ -0,0 +1,113 @@
+// Boost.Geometry
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// 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
+
+// Use, modification and distribution is subject to the Boost Software 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_SIDE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_HPP
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/formulas/spherical.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+#include <boost/geometry/strategies/side.hpp>
+//#include <boost/geometry/strategies/concepts/side_concept.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace side
+{
+
+
+/*!
+\brief Check at which side of a segment a point lies
+ left of segment (> 0), right of segment (< 0), on segment (0)
+\ingroup strategies
+\tparam FormulaPolicy Geodesic solution formula policy.
+\tparam Spheroid Reference model of coordinate system.
+\tparam CalculationType \tparam_calculation
+ */
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic
+{
+public:
+ geographic()
+ {}
+
+ explicit geographic(Spheroid const& model)
+ : m_model(model)
+ {}
+
+ template <typename P1, typename P2, typename P>
+ inline int apply(P1 const& p1, P2 const& p2, P const& p) const
+ {
+ typedef typename promote_floating_point
+ <
+ typename select_calculation_type_alt
+ <
+ CalculationType,
+ P1, P2, P
+ >::type
+ >::type calc_t;
+
+ typedef typename FormulaPolicy::template inverse
+ <calc_t, false, true, false, false, false> inverse_formula;
+
+ calc_t a1p = azimuth<calc_t, inverse_formula>(p1, p, m_model);
+ calc_t a12 = azimuth<calc_t, inverse_formula>(p1, p2, m_model);
+
+ return formula::azimuth_side_value(a1p, a12);
+ }
+
+private:
+ template <typename ResultType,
+ typename InverseFormulaType,
+ typename Point1,
+ typename Point2,
+ typename ModelT>
+ static inline ResultType azimuth(Point1 const& point1, Point2 const& point2,
+ ModelT const& model)
+ {
+ return InverseFormulaType::apply(get_as_radian<0>(point1),
+ get_as_radian<1>(point1),
+ get_as_radian<0>(point2),
+ get_as_radian<1>(point2),
+ model).azimuth;
+ }
+
+ Spheroid m_model;
+};
+
+
+}} // namespace strategy::side
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_HPP
diff --git a/boost/geometry/strategies/geographic/side_andoyer.hpp b/boost/geometry/strategies/geographic/side_andoyer.hpp
index c3e71cd1cd..204e45f6e2 100644
--- a/boost/geometry/strategies/geographic/side_andoyer.hpp
+++ b/boost/geometry/strategies/geographic/side_andoyer.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015, 2016.
-// Modifications copyright (c) 2014-2016 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
@@ -15,9 +15,7 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_ANDOYER_HPP
-#include <boost/geometry/formulas/andoyer_inverse.hpp>
-
-#include <boost/geometry/strategies/geographic/side_detail.hpp>
+#include <boost/geometry/strategies/geographic/side.hpp>
namespace boost { namespace geometry
@@ -31,17 +29,24 @@ namespace strategy { namespace side
\brief Check at which side of a segment a point lies
left of segment (> 0), right of segment (< 0), on segment (0)
\ingroup strategies
-\tparam Model Reference model of coordinate system.
+\tparam Spheroid Reference model of coordinate system.
\tparam CalculationType \tparam_calculation
*/
-template <typename Model, typename CalculationType = void>
+template
+<
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
class andoyer
- : public detail::by_azimuth<geometry::formula::andoyer_inverse, Model, CalculationType>
+ : public side::geographic<strategy::andoyer, Spheroid, CalculationType>
{
- typedef detail::by_azimuth<geometry::formula::andoyer_inverse, Model, CalculationType> base_t;
+ typedef side::geographic<strategy::andoyer, Spheroid, CalculationType> base_t;
public:
- andoyer(Model const& model = Model())
+ andoyer()
+ {}
+
+ explicit andoyer(Spheroid const& model)
: base_t(model)
{}
};
diff --git a/boost/geometry/strategies/geographic/side_detail.hpp b/boost/geometry/strategies/geographic/side_detail.hpp
deleted file mode 100644
index ce1b47c88e..0000000000
--- a/boost/geometry/strategies/geographic/side_detail.hpp
+++ /dev/null
@@ -1,139 +0,0 @@
-// Boost.Geometry
-
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-
-// This file was modified by Oracle on 2014, 2015, 2016.
-// Modifications copyright (c) 2014-2016 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_STRATEGIES_GEOGRAPHIC_SIDE_DETAIL_HPP
-#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_DETAIL_HPP
-
-#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/access.hpp>
-#include <boost/geometry/core/radian_access.hpp>
-#include <boost/geometry/core/radius.hpp>
-
-#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
-#include <boost/geometry/util/select_calculation_type.hpp>
-
-#include <boost/geometry/strategies/side.hpp>
-//#include <boost/geometry/strategies/concepts/side_concept.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-
-namespace strategy { namespace side
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail
-{
-
-/*!
-\brief Check at which side of a segment a point lies
- left of segment (> 0), right of segment (< 0), on segment (0)
-\ingroup strategies
-\tparam InverseFormula Geodesic inverse solution formula.
-\tparam Model Reference model of coordinate system.
-\tparam CalculationType \tparam_calculation
- */
-template <template<typename, bool, bool, bool, bool, bool> class InverseFormula,
- typename Model,
- typename CalculationType = void>
-class by_azimuth
-{
-public:
- by_azimuth(Model const& model = Model())
- : m_model(model)
- {}
-
- template <typename P1, typename P2, typename P>
- inline int apply(P1 const& p1, P2 const& p2, P const& p)
- {
- typedef typename promote_floating_point
- <
- typename select_calculation_type_alt
- <
- CalculationType,
- P1, P2, P
- >::type
- >::type calc_t;
-
- typedef InverseFormula<calc_t, false, true, false, false, false> inverse_formula;
-
- calc_t a1p = azimuth<calc_t, inverse_formula>(p1, p, m_model);
- calc_t a12 = azimuth<calc_t, inverse_formula>(p1, p2, m_model);
-
- calc_t const pi = math::pi<calc_t>();
-
- // instead of the formula from XTD
- //calc_t a_diff = asin(sin(a1p - a12));
-
- calc_t a_diff = a1p - a12;
- // normalize, angle in [-pi, pi]
- while ( a_diff > pi )
- a_diff -= calc_t(2) * pi;
- while ( a_diff < -pi )
- a_diff += calc_t(2) * pi;
-
- // NOTE: in general it shouldn't be required to support the pi/-pi case
- // because in non-cartesian systems it makes sense to check the side
- // only "between" the endpoints.
- // However currently the winding strategy calls the side strategy
- // for vertical segments to check if the point is "between the endpoints.
- // This could be avoided since the side strategy is not required for that
- // because meridian is the shortest path. So a difference of
- // longitudes would be sufficient (of course normalized to [-pi, pi]).
-
- // NOTE: with the above said, the pi/-pi check is temporary
- // however in case if this was required
- // the geodesics on ellipsoid aren't "symmetrical"
- // therefore instead of comparing a_diff to pi and -pi
- // one should probably use inverse azimuths and compare
- // the difference to 0 as well
-
- // positive azimuth is on the right side
- return math::equals(a_diff, 0)
- || math::equals(a_diff, pi)
- || math::equals(a_diff, -pi) ? 0
- : a_diff > 0 ? -1 // right
- : 1; // left
- }
-
-private:
- template <typename ResultType,
- typename InverseFormulaType,
- typename Point1,
- typename Point2,
- typename ModelT>
- static inline ResultType azimuth(Point1 const& point1, Point2 const& point2, ModelT const& model)
- {
- return InverseFormulaType::apply(get_as_radian<0>(point1),
- get_as_radian<1>(point1),
- get_as_radian<0>(point2),
- get_as_radian<1>(point2),
- model).azimuth;
- }
-
- Model m_model;
-};
-
-} // detail
-#endif // DOXYGEN_NO_DETAIL
-
-}} // namespace strategy::side
-
-
-}} // namespace boost::geometry
-
-
-#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_DETAIL_HPP
diff --git a/boost/geometry/strategies/geographic/side_thomas.hpp b/boost/geometry/strategies/geographic/side_thomas.hpp
index 96b0323307..e6f8d77b58 100644
--- a/boost/geometry/strategies/geographic/side_thomas.hpp
+++ b/boost/geometry/strategies/geographic/side_thomas.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015, 2016.
-// Modifications copyright (c) 2014-2016 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
@@ -15,9 +15,7 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_THOMAS_HPP
-#include <boost/geometry/formulas/thomas_inverse.hpp>
-
-#include <boost/geometry/strategies/geographic/side_detail.hpp>
+#include <boost/geometry/strategies/geographic/side.hpp>
namespace boost { namespace geometry
@@ -31,17 +29,24 @@ namespace strategy { namespace side
\brief Check at which side of a segment a point lies
left of segment (> 0), right of segment (< 0), on segment (0)
\ingroup strategies
-\tparam Model Reference model of coordinate system.
+\tparam Spheroid Reference model of coordinate system.
\tparam CalculationType \tparam_calculation
*/
-template <typename Model, typename CalculationType = void>
+template
+<
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
class thomas
- : public detail::by_azimuth<geometry::formula::thomas_inverse, Model, CalculationType>
+ : public side::geographic<strategy::thomas, Spheroid, CalculationType>
{
- typedef detail::by_azimuth<geometry::formula::thomas_inverse, Model, CalculationType> base_t;
+ typedef side::geographic<strategy::thomas, Spheroid, CalculationType> base_t;
public:
- thomas(Model const& model = Model())
+ thomas()
+ {}
+
+ explicit thomas(Spheroid const& model)
: base_t(model)
{}
};
diff --git a/boost/geometry/strategies/geographic/side_vincenty.hpp b/boost/geometry/strategies/geographic/side_vincenty.hpp
index 103277a8bd..b2f51b0901 100644
--- a/boost/geometry/strategies/geographic/side_vincenty.hpp
+++ b/boost/geometry/strategies/geographic/side_vincenty.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015, 2016.
-// Modifications copyright (c) 2014-2016 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
@@ -15,9 +15,7 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_VINCENTY_HPP
-#include <boost/geometry/formulas/vincenty_inverse.hpp>
-
-#include <boost/geometry/strategies/geographic/side_detail.hpp>
+#include <boost/geometry/strategies/geographic/side.hpp>
namespace boost { namespace geometry
@@ -31,17 +29,24 @@ namespace strategy { namespace side
\brief Check at which side of a segment a point lies
left of segment (> 0), right of segment (< 0), on segment (0)
\ingroup strategies
-\tparam Model Reference model of coordinate system.
+\tparam Spheroid Reference model of coordinate system.
\tparam CalculationType \tparam_calculation
*/
-template <typename Model, typename CalculationType = void>
+template
+<
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
class vincenty
- : public detail::by_azimuth<geometry::formula::vincenty_inverse, Model, CalculationType>
+ : public side::geographic<strategy::vincenty, Spheroid, CalculationType>
{
- typedef detail::by_azimuth<geometry::formula::vincenty_inverse, Model, CalculationType> base_t;
+ typedef side::geographic<strategy::vincenty, Spheroid, CalculationType> base_t;
public:
- vincenty(Model const& model = Model())
+ vincenty()
+ {}
+
+ explicit vincenty(Spheroid const& model)
: base_t(model)
{}
};
diff --git a/boost/geometry/strategies/intersection.hpp b/boost/geometry/strategies/intersection.hpp
index f51c5cb206..e5662c9e46 100644
--- a/boost/geometry/strategies/intersection.hpp
+++ b/boost/geometry/strategies/intersection.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2016, Oracle and/or its affiliates.
+// Copyright (c) 2016-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,
@@ -30,10 +30,9 @@ namespace services
\brief Traits class binding a segments intersection strategy to a coordinate system
\ingroup util
\tparam CSTag tag of coordinate system of point-type
-\tparam Policy intersection policy
\tparam CalculationType \tparam_calculation
*/
-template <typename CSTag, typename Policy, typename CalculationType = void>
+template <typename CSTag, typename CalculationType = void>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
diff --git a/boost/geometry/strategies/intersection_strategies.hpp b/boost/geometry/strategies/intersection_strategies.hpp
index 0452c4692c..a173505804 100644
--- a/boost/geometry/strategies/intersection_strategies.hpp
+++ b/boost/geometry/strategies/intersection_strategies.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2016.
-// Modifications copyright (c) 2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016, 2017.
+// Modifications copyright (c) 2016-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,
@@ -22,10 +22,10 @@
#include <boost/geometry/policies/relate/tupled.hpp>
#include <boost/geometry/strategies/intersection.hpp>
-#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
+#include <boost/geometry/strategies/side.hpp>
-#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
+#include <boost/geometry/strategies/cartesian/intersection.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/spherical/intersection.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
@@ -70,17 +70,18 @@ private :
> ip_type;
public:
+ typedef policies::relate::segments_tupled
+ <
+ policies::relate::segments_intersection_points
+ <
+ ip_type
+ > ,
+ policies::relate::segments_direction
+ > intersection_policy_type;
+
typedef typename strategy::intersection::services::default_strategy
<
Tag,
- policies::relate::segments_tupled
- <
- policies::relate::segments_intersection_points
- <
- ip_type
- > ,
- policies::relate::segments_direction
- >,
CalculationType
>::type segment_intersection_strategy_type;
diff --git a/boost/geometry/strategies/relate.hpp b/boost/geometry/strategies/relate.hpp
new file mode 100644
index 0000000000..ffeed78959
--- /dev/null
+++ b/boost/geometry/strategies/relate.hpp
@@ -0,0 +1,177 @@
+// 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_STRATEGIES_RELATE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_RELATE_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/topological_dimension.hpp>
+
+#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/within.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy
+{
+
+namespace point_in_geometry
+{
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template
+<
+ typename Point,
+ typename Geometry,
+ typename Tag1 = typename tag<Point>::type,
+ typename Tag2 = typename tag<Geometry>::type
+>
+struct default_strategy
+ : strategy::within::services::default_strategy
+ <
+ Point,
+ Geometry
+ >
+{
+ typedef typename default_strategy::type within_strategy_type;
+
+ typedef typename strategy::covered_by::services::default_strategy
+ <
+ Point,
+ Geometry
+ >::type covered_by_strategy_type;
+
+ static const bool same_strategies = boost::is_same<within_strategy_type, covered_by_strategy_type>::value;
+ BOOST_MPL_ASSERT_MSG((same_strategies),
+ DEFAULT_WITHIN_AND_COVERED_BY_STRATEGIES_NOT_COMPATIBLE,
+ (within_strategy_type, covered_by_strategy_type));
+};
+
+template<typename Point, typename Geometry>
+struct default_strategy<Point, Geometry, point_tag, point_tag>
+ : strategy::within::services::default_strategy<Point, Geometry>
+{};
+
+template<typename Point, typename Geometry>
+struct default_strategy<Point, Geometry, point_tag, multi_point_tag>
+ : strategy::within::services::default_strategy<Point, Geometry>
+{};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+} // namespace point_in_geometry
+
+namespace relate
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Geometry>
+struct default_intersection_strategy
+ : strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >
+{};
+
+template <typename PointLike, typename Geometry>
+struct default_point_in_geometry_strategy
+ : point_in_geometry::services::default_strategy
+ <
+ typename point_type<PointLike>::type,
+ Geometry
+ >
+{};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ int TopDim1 = geometry::topological_dimension<Geometry1>::value,
+ int TopDim2 = geometry::topological_dimension<Geometry2>::value
+>
+struct default_strategy
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THESE_TYPES
+ , (types<Geometry1, Geometry2>)
+ );
+};
+
+template <typename PointLike1, typename PointLike2>
+struct default_strategy<PointLike1, PointLike2, 0, 0>
+ : detail::default_point_in_geometry_strategy<PointLike1, PointLike2>
+{};
+
+template <typename PointLike, typename Geometry, int TopDim2>
+struct default_strategy<PointLike, Geometry, 0, TopDim2>
+ : detail::default_point_in_geometry_strategy<PointLike, Geometry>
+{};
+
+template <typename Geometry, typename PointLike, int TopDim1>
+struct default_strategy<Geometry, PointLike, TopDim1, 0>
+ : detail::default_point_in_geometry_strategy<PointLike, Geometry>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct default_strategy<Geometry1, Geometry2, 1, 1>
+ : detail::default_intersection_strategy<Geometry1>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct default_strategy<Geometry1, Geometry2, 1, 2>
+ : detail::default_intersection_strategy<Geometry1>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct default_strategy<Geometry1, Geometry2, 2, 1>
+ : detail::default_intersection_strategy<Geometry1>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct default_strategy<Geometry1, Geometry2, 2, 2>
+ : detail::default_intersection_strategy<Geometry1>
+{};
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+} // namespace relate
+
+} // namespace strategy
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_RELATE_HPP
diff --git a/boost/geometry/strategies/side.hpp b/boost/geometry/strategies/side.hpp
index 376f2fdf1b..9aaa2bdddc 100644
--- a/boost/geometry/strategies/side.hpp
+++ b/boost/geometry/strategies/side.hpp
@@ -30,16 +30,16 @@ namespace services
/*!
\brief Traits class binding a side determination strategy to a coordinate system
\ingroup util
-\tparam Tag tag of coordinate system of point-type
+\tparam CSTag tag of coordinate system of point-type
\tparam CalculationType \tparam_calculation
*/
-template <typename Tag, typename CalculationType = void>
+template <typename CSTag, typename CalculationType = void>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_TYPE
- , (types<Tag>)
+ , (types<CSTag>)
);
};
diff --git a/boost/geometry/strategies/spherical/area.hpp b/boost/geometry/strategies/spherical/area.hpp
new file mode 100644
index 0000000000..206b734548
--- /dev/null
+++ b/boost/geometry/strategies/spherical/area.hpp
@@ -0,0 +1,182 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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_AREA_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HPP
+
+
+#include <boost/geometry/formulas/area_formulas.hpp>
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+#include <boost/geometry/strategies/area.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace area
+{
+
+/*!
+\brief Spherical area calculation
+\ingroup strategies
+\details Calculates area on the surface of a sphere using the trapezoidal rule
+\tparam PointOfSegment \tparam_segment_point
+\tparam CalculationType \tparam_calculation
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
+}
+*/
+template
+<
+ typename PointOfSegment,
+ typename CalculationType = void
+>
+class spherical
+{
+ // Enables special handling of long segments
+ static const bool LongSegment = false;
+
+typedef typename boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename coordinate_type<PointOfSegment>::type,
+ double
+ >::type,
+ CalculationType
+ >::type CT;
+
+protected :
+ struct excess_sum
+ {
+ CT m_sum;
+
+ // Keep track if encircles some pole
+ size_t m_crosses_prime_meridian;
+
+ inline excess_sum()
+ : m_sum(0)
+ , m_crosses_prime_meridian(0)
+ {}
+ template <typename SphereType>
+ inline CT area(SphereType sphere) const
+ {
+ CT result;
+ CT radius = geometry::get_radius<0>(sphere);
+
+ // Encircles pole
+ if(m_crosses_prime_meridian % 2 == 1)
+ {
+ size_t times_crosses_prime_meridian
+ = 1 + (m_crosses_prime_meridian / 2);
+
+ result = CT(2)
+ * geometry::math::pi<CT>()
+ * times_crosses_prime_meridian
+ - geometry::math::abs(m_sum);
+
+ if(geometry::math::sign<CT>(m_sum) == 1)
+ {
+ result = - result;
+ }
+
+ } else {
+ result = m_sum;
+ }
+
+ result *= radius * radius;
+
+ return result;
+ }
+ };
+
+public :
+ typedef CT return_type;
+ typedef PointOfSegment segment_point_type;
+ typedef excess_sum state_type;
+ typedef geometry::srs::sphere<CT> sphere_type;
+
+ // For backward compatibility reasons the radius is set to 1
+ inline spherical()
+ : m_sphere(1.0)
+ {}
+
+ template <typename T>
+ explicit inline spherical(geometry::srs::sphere<T> const& sphere)
+ : m_sphere(geometry::get_radius<0>(sphere))
+ {}
+
+ explicit inline spherical(CT const& radius)
+ : m_sphere(radius)
+ {}
+
+ inline void apply(PointOfSegment const& p1,
+ PointOfSegment const& p2,
+ excess_sum& state) const
+ {
+ if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
+ {
+
+ state.m_sum += geometry::formula::area_formulas
+ <CT>::template spherical<LongSegment>(p1, p2);
+
+ // Keep track whenever a segment crosses the prime meridian
+ geometry::formula::area_formulas
+ <CT>::crosses_prime_meridian(p1, p2, state);
+
+ }
+ }
+
+ inline return_type result(excess_sum const& state) const
+ {
+ return state.area(m_sphere);
+ }
+
+private :
+ /// srs Sphere
+ sphere_type m_sphere;
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+
+template <typename Point>
+struct default_strategy<spherical_equatorial_tag, Point>
+{
+ typedef strategy::area::spherical<Point> type;
+};
+
+// Note: spherical polar coordinate system requires "get_as_radian_equatorial"
+template <typename Point>
+struct default_strategy<spherical_polar_tag, Point>
+{
+ typedef strategy::area::spherical<Point> type;
+};
+
+} // namespace services
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::area
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HPP
diff --git a/boost/geometry/strategies/spherical/area_huiller.hpp b/boost/geometry/strategies/spherical/area_huiller.hpp
deleted file mode 100644
index 37d8d20124..0000000000
--- a/boost/geometry/strategies/spherical/area_huiller.hpp
+++ /dev/null
@@ -1,214 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, 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
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP
-#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP
-
-
-
-#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
-
-#include <boost/geometry/core/radian_access.hpp>
-#include <boost/geometry/util/math.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-namespace strategy { namespace area
-{
-
-
-
-/*!
-\brief Area calculation by spherical excess / Huiller's formula
-\ingroup strategies
-\tparam PointOfSegment point type of segments of rings/polygons
-\tparam CalculationType \tparam_calculation
-\author Barend Gehrels. Adapted from:
-- http://webdocs.cs.ualberta.ca/~graphics/books/GraphicsGems/gemsiv/sph_poly.c
-- http://tog.acm.org/resources/GraphicsGems/gemsiv/sph_poly.c
-- http://williams.best.vwh.net/avform.htm
-\note The version in Graphics Gems IV (page 132-137) didn't account for
-polygons crossing the 0 and 180 meridians. The fix for this algorithm
-can be found in Graphics Gems V (pages 45-46). See:
-- http://kysmykseka.net/koti/wizardry/Game%20Development/Programming/Graphics%20Gems%204.pdf
-- http://kysmykseka.net/koti/wizardry/Game%20Development/Programming/Graphics%20Gems%205.pdf
-\note This version works for convex and non-convex polygons, for 180 meridian
-crossing polygons and for polygons with holes. However, some cases (especially
-180 meridian cases) must still be checked.
-\note The version which sums angles, which is often seen, doesn't handle non-convex
-polygons correctly.
-\note The version which sums longitudes, see http://hdl.handle.net/2014/40409,
-is simple and works well in most cases but not in 180 meridian crossing cases.
-This probably could be solved.
-
-\note This version is made for spherical equatorial coordinate systems
-
-\qbk{
-
-[heading Example]
-[area_with_strategy]
-[area_with_strategy_output]
-
-
-[heading See also]
-[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
-}
-
-*/
-template
-<
- typename PointOfSegment,
- typename CalculationType = void
->
-class huiller
-{
-typedef typename boost::mpl::if_c
- <
- boost::is_void<CalculationType>::type::value,
- typename select_most_precise
- <
- typename coordinate_type<PointOfSegment>::type,
- double
- >::type,
- CalculationType
- >::type calculation_type;
-
-protected :
- struct excess_sum
- {
- calculation_type sum;
-
- // Distances are calculated on unit sphere here
- strategy::distance::haversine<calculation_type> distance_over_unit_sphere;
-
-
- inline excess_sum()
- : sum(0)
- , distance_over_unit_sphere(1)
- {}
- inline calculation_type area(calculation_type radius) const
- {
- return - sum * radius * radius;
- }
- };
-
-public :
- typedef calculation_type return_type;
- typedef PointOfSegment segment_point_type;
- typedef excess_sum state_type;
-
- inline huiller(calculation_type radius = 1.0)
- : m_radius(radius)
- {}
-
- inline void apply(PointOfSegment const& p1,
- PointOfSegment const& p2,
- excess_sum& state) const
- {
- if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
- {
- calculation_type const half = 0.5;
- calculation_type const two = 2.0;
- calculation_type const four = 4.0;
- calculation_type const pi
- = geometry::math::pi<calculation_type>();
- calculation_type const two_pi
- = geometry::math::two_pi<calculation_type>();
- calculation_type const half_pi
- = geometry::math::half_pi<calculation_type>();
-
- // Distance p1 p2
- calculation_type a = state.distance_over_unit_sphere.apply(p1, p2);
-
- // Sides on unit sphere to south pole
- calculation_type b = half_pi - geometry::get_as_radian<1>(p2);
- calculation_type c = half_pi - geometry::get_as_radian<1>(p1);
-
- // Semi parameter
- calculation_type s = half * (a + b + c);
-
- // E: spherical excess, using l'Huiller's formula
- // [tg(e / 4)]2 = tg[s / 2] tg[(s-a) / 2] tg[(s-b) / 2] tg[(s-c) / 2]
- calculation_type excess = four
- * atan(geometry::math::sqrt(geometry::math::abs(tan(s / two)
- * tan((s - a) / two)
- * tan((s - b) / two)
- * tan((s - c) / two))));
-
- excess = geometry::math::abs(excess);
-
- // In right direction: positive, add area. In left direction: negative, subtract area.
- // Longitude comparisons are not so obvious. If one is negative and other is positive,
- // we have to take the dateline into account.
-
- calculation_type lon_diff = geometry::get_as_radian<0>(p2)
- - geometry::get_as_radian<0>(p1);
- if (lon_diff <= 0)
- {
- lon_diff += two_pi;
- }
-
- if (lon_diff > pi)
- {
- excess = -excess;
- }
-
- state.sum += excess;
- }
- }
-
- inline return_type result(excess_sum const& state) const
- {
- return state.area(m_radius);
- }
-
-private :
- /// Radius of the sphere
- calculation_type m_radius;
-};
-
-#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-
-namespace services
-{
-
-
-template <typename Point>
-struct default_strategy<spherical_equatorial_tag, Point>
-{
- typedef strategy::area::huiller<Point> type;
-};
-
-// Note: spherical polar coordinate system requires "get_as_radian_equatorial"
-/***template <typename Point>
-struct default_strategy<spherical_polar_tag, Point>
-{
- typedef strategy::area::huiller<Point> type;
-};***/
-
-} // namespace services
-
-#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-
-
-}} // namespace strategy::area
-
-
-
-
-}} // namespace boost::geometry
-
-#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP
diff --git a/boost/geometry/strategies/spherical/azimuth.hpp b/boost/geometry/strategies/spherical/azimuth.hpp
new file mode 100644
index 0000000000..3c208fe2e2
--- /dev/null
+++ b/boost/geometry/strategies/spherical/azimuth.hpp
@@ -0,0 +1,87 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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_AZIMUTH_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AZIMUTH_HPP
+
+
+#include <boost/geometry/strategies/azimuth.hpp>
+#include <boost/geometry/formulas/spherical.hpp>
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_void.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace azimuth
+{
+
+template
+<
+ typename CalculationType = void
+>
+class spherical
+{
+public :
+
+ inline spherical()
+ {}
+
+ template <typename T>
+ static inline void apply(T const& lon1_rad, T const& lat1_rad,
+ T const& lon2_rad, T const& lat2_rad,
+ T& a1, T& a2)
+ {
+ 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, true>(
+ calc_t(lon1_rad), calc_t(lat1_rad),
+ calc_t(lon2_rad), calc_t(lat2_rad));
+
+ a1 = result.azimuth;
+ a2 = result.reverse_azimuth;
+ }
+
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<spherical_equatorial_tag, CalculationType>
+{
+ typedef strategy::azimuth::spherical<CalculationType> type;
+};
+
+/*
+template <typename CalculationType>
+struct default_strategy<spherical_polar_tag, CalculationType>
+{
+ typedef strategy::azimuth::spherical<CalculationType> type;
+};
+*/
+}
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}} // namespace strategy::azimuth
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AZIMUTH_HPP
diff --git a/boost/geometry/strategies/spherical/envelope_segment.hpp b/boost/geometry/strategies/spherical/envelope_segment.hpp
new file mode 100644
index 0000000000..98f085fe73
--- /dev/null
+++ b/boost/geometry/strategies/spherical/envelope_segment.hpp
@@ -0,0 +1,86 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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_ENVELOPE_SEGMENT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_SEGMENT_HPP
+
+#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
+#include <boost/geometry/algorithms/detail/normalize.hpp>
+#include <boost/geometry/strategies/envelope.hpp>
+#include <boost/geometry/strategies/spherical/azimuth.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace envelope
+{
+
+template
+<
+ typename CalculationType = void
+>
+class spherical_segment
+{
+public :
+
+ inline spherical_segment()
+ {}
+
+ template <typename Point1, typename Point2, typename Box>
+ inline void
+ apply(Point1 const& point1, Point2 const& point2, Box& box) const
+ {
+ Point1 p1_normalized = detail::return_normalized<Point1>(point1);
+ Point2 p2_normalized = detail::return_normalized<Point2>(point2);
+
+ geometry::strategy::azimuth::spherical<CalculationType> azimuth_spherical;
+
+ typedef typename coordinate_system<Point1>::type::units units_type;
+
+ geometry::detail::envelope::envelope_segment_impl<spherical_equatorial_tag>
+ ::template apply<units_type>(geometry::get<0>(p1_normalized),
+ geometry::get<1>(p1_normalized),
+ geometry::get<0>(p2_normalized),
+ geometry::get<1>(p2_normalized),
+ box,
+ azimuth_spherical);
+
+ }
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<spherical_equatorial_tag, CalculationType>
+{
+ typedef strategy::envelope::spherical_segment<CalculationType> type;
+};
+
+
+template <typename CalculationType>
+struct default_strategy<spherical_polar_tag, CalculationType>
+{
+ typedef strategy::envelope::spherical_segment<CalculationType> type;
+};
+
+}
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::envelope
+
+}} //namepsace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_SEGMENT_HPP
+
diff --git a/boost/geometry/strategies/spherical/intersection.hpp b/boost/geometry/strategies/spherical/intersection.hpp
index 4ffc853aad..5d37583333 100644
--- a/boost/geometry/strategies/spherical/intersection.hpp
+++ b/boost/geometry/strategies/spherical/intersection.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2016, Oracle and/or its affiliates.
+// Copyright (c) 2016-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,
@@ -25,6 +25,7 @@
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/cross_product.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
+#include <boost/geometry/arithmetic/normalize.hpp>
#include <boost/geometry/formulas/spherical.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
@@ -32,9 +33,16 @@
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
-#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
+#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
+#include <boost/geometry/strategies/side.hpp>
+#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/ssf.hpp>
+#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
@@ -68,13 +76,80 @@ namespace strategy { namespace intersection
// For now, intersection points near the endpoints are checked explicitly if needed (if the IP is near the endpoint)
// to generate precise result for them. Only the crossing (i) case may suffer from lower precision.
-template <typename Policy, typename CalculationType = void>
-struct relate_spherical_segments
+template
+<
+ typename CalcPolicy,
+ typename CalculationType = void
+>
+struct ecef_segments
{
- typedef typename Policy::return_type return_type;
+ typedef side::spherical_side_formula<CalculationType> side_strategy_type;
+
+ static inline side_strategy_type get_side_strategy()
+ {
+ return side_strategy_type();
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ struct point_in_geometry_strategy
+ {
+ typedef strategy::within::winding
+ <
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type,
+ side_strategy_type,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry1, typename Geometry2>
+ static inline typename point_in_geometry_strategy<Geometry1, Geometry2>::type
+ get_point_in_geometry_strategy()
+ {
+ typedef typename point_in_geometry_strategy
+ <
+ Geometry1, Geometry2
+ >::type strategy_type;
+ return strategy_type();
+ }
+
+ template <typename Geometry>
+ struct area_strategy
+ {
+ typedef area::spherical
+ <
+ typename point_type<Geometry>::type,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry>
+ static inline typename area_strategy<Geometry>::type get_area_strategy()
+ {
+ typedef typename area_strategy<Geometry>::type strategy_type;
+ return strategy_type();
+ }
+
+ template <typename Geometry>
+ struct distance_strategy
+ {
+ typedef distance::haversine
+ <
+ typename coordinate_type<Geometry>::type,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry>
+ static inline typename distance_strategy<Geometry>::type get_distance_strategy()
+ {
+ typedef typename distance_strategy<Geometry>::type strategy_type;
+ return 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
template <typename CoordinateType, typename SegmentRatio, typename Vector3d>
struct segment_intersection_info
{
@@ -83,6 +158,10 @@ struct relate_spherical_segments
CoordinateType, double
>::type promoted_type;
+ segment_intersection_info(CalcPolicy const& calc)
+ : calc_policy(calc)
+ {}
+
promoted_type comparable_length_a() const
{
return robust_ra.denominator();
@@ -110,7 +189,7 @@ struct relate_spherical_segments
if (ip_flag == ipi_inters)
{
// TODO: assign the rest of coordinates
- point = formula::cart3d_to_sph<Point>(intersection_point);
+ point = calc_policy.template from_cart3d<Point>(intersection_point);
}
else if (ip_flag == ipi_at_a1)
{
@@ -134,12 +213,21 @@ struct relate_spherical_segments
SegmentRatio robust_ra;
SegmentRatio robust_rb;
intersection_point_flag ip_flag;
+
+ CalcPolicy const& calc_policy;
};
// Relate segments a and b
- template <typename Segment1, typename Segment2, typename RobustPolicy>
- static inline return_type apply(Segment1 const& a, Segment2 const& b,
- RobustPolicy const& robust_policy)
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename Policy,
+ typename RobustPolicy
+ >
+ static inline typename Policy::return_type
+ apply(Segment1 const& a, Segment2 const& b,
+ Policy const& policy, RobustPolicy const& robust_policy)
{
typedef typename point_type<Segment1>::type point1_t;
typedef typename point_type<Segment2>::type point2_t;
@@ -152,15 +240,30 @@ struct relate_spherical_segments
detail::assign_point_from_index<0>(b, b1);
detail::assign_point_from_index<1>(b, b2);
- return apply(a, b, robust_policy, a1, a2, b1, b2);
+ return apply(a, b, policy, robust_policy, a1, a2, b1, b2);
}
// Relate segments a and b
- template <typename Segment1, typename Segment2, typename RobustPolicy, typename Point1, typename Point2>
- static inline return_type apply(Segment1 const& a, Segment2 const& b,
- RobustPolicy const&,
- Point1 const& a1, Point1 const& a2, Point2 const& b1, Point2 const& b2)
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename Policy,
+ typename RobustPolicy,
+ typename Point1,
+ typename Point2
+ >
+ static inline typename Policy::return_type
+ apply(Segment1 const& a, Segment2 const& b,
+ Policy const&, RobustPolicy const&,
+ Point1 const& a1, Point1 const& a2, Point2 const& b1, Point2 const& b2)
{
+ // For now create it using default constructor. In the future it could
+ // be stored in strategy. However then apply() wouldn't be static and
+ // all relops and setops would have to take the strategy or model.
+ // Initialize explicitly to prevent compiler errors in case of PoD type
+ CalcPolicy const calc_policy = CalcPolicy();
+
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
@@ -185,25 +288,29 @@ struct relate_spherical_segments
typedef model::point<calc_t, 3, cs::cartesian> vec3d_t;
- using namespace formula;
- vec3d_t const a1v = sph_to_cart3d<vec3d_t>(a1);
- vec3d_t const a2v = sph_to_cart3d<vec3d_t>(a2);
- vec3d_t const b1v = sph_to_cart3d<vec3d_t>(b1);
- vec3d_t const b2v = sph_to_cart3d<vec3d_t>(b2);
+ vec3d_t const a1v = calc_policy.template to_cart3d<vec3d_t>(a1);
+ vec3d_t const a2v = calc_policy.template to_cart3d<vec3d_t>(a2);
+ vec3d_t const b1v = calc_policy.template to_cart3d<vec3d_t>(b1);
+ vec3d_t const b2v = calc_policy.template to_cart3d<vec3d_t>(b2);
- vec3d_t norm1 = cross_product(a1v, a2v);
- vec3d_t norm2 = cross_product(b1v, b2v);
-
side_info sides;
- // not normalized normals, the same as in SSF
- sides.set<0>(sph_side_value(norm2, a1v), sph_side_value(norm2, a2v));
+
+ 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>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
- // not normalized normals, the same as in SSF
- sides.set<1>(sph_side_value(norm1, b1v), sph_side_value(norm1, b2v));
+
+ 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>())
{
// Both points are at same side of other segment, we can leave
@@ -212,13 +319,10 @@ struct relate_spherical_segments
// NOTE: at this point the segments may still be disjoint
- bool collinear = sides.collinear();
-
- calc_t const len1 = math::sqrt(dot_product(norm1, norm1));
- calc_t const len2 = math::sqrt(dot_product(norm2, norm2));
+ calc_t len1, len2;
- // point or opposite sides of a sphere, assume point
- if (math::equals(len1, c0))
+ // point or opposite sides of a sphere/spheroid, assume point
+ if (! detail::vec_normalize(plane1.normal, len1))
{
a_is_point = true;
if (sides.get<0, 0>() == 0 || sides.get<0, 1>() == 0)
@@ -226,13 +330,8 @@ struct relate_spherical_segments
sides.set<0>(0, 0);
}
}
- else
- {
- // normalize
- divide_value(norm1, len1);
- }
- if (math::equals(len2, c0))
+ if (! detail::vec_normalize(plane2.normal, len2))
{
b_is_point = true;
if (sides.get<1, 0>() == 0 || sides.get<1, 1>() == 0)
@@ -240,11 +339,6 @@ struct relate_spherical_segments
sides.set<1>(0, 0);
}
}
- else
- {
- // normalize
- divide_value(norm2, len2);
- }
// check both degenerated once more
if (a_is_point && b_is_point)
@@ -255,16 +349,42 @@ struct relate_spherical_segments
;
}
+ // NOTE: at this point the segments may still be disjoint
// NOTE: at this point one of the segments may be degenerated
- // and the segments may still be disjoint
- calc_t dot_n1n2 = dot_product(norm1, norm2);
+ bool collinear = sides.collinear();
+
+ if (! collinear)
+ {
+ // NOTE: for some approximations it's possible that both points may lie
+ // on the same geodesic but still some of the sides may be != 0.
+ // This is e.g. true for long segments represented as elliptic arcs
+ // with origin different than the center of the coordinate system.
+ // So make the sides consistent
+
+ // WARNING: the side strategy doesn't have the info about the other
+ // segment so it may return results inconsistent with this intersection
+ // strategy, as it checks both segments for consistency
+
+ if (sides.get<0, 0>() == 0 && sides.get<0, 1>() == 0)
+ {
+ collinear = true;
+ sides.set<1>(0, 0);
+ }
+ else if (sides.get<1, 0>() == 0 && sides.get<1, 1>() == 0)
+ {
+ collinear = true;
+ sides.set<0>(0, 0);
+ }
+ }
+
+ calc_t dot_n1n2 = dot_product(plane1.normal, plane2.normal);
// NOTE: this is technically not needed since theoretically above sides
// are calculated, but just in case check the normals.
// Have in mind that SSF side strategy doesn't check this.
// collinear if normals are equal or opposite: cos(a) in {-1, 1}
- if (!collinear && math::equals(math::abs(dot_n1n2), c1))
+ if (! collinear && math::equals(math::abs(dot_n1n2), c1))
{
collinear = true;
sides.set<0>(0, 0);
@@ -275,12 +395,12 @@ struct relate_spherical_segments
{
if (a_is_point)
{
- return collinear_one_degenerted<calc_t>(a, true, b1, b2, a1, a2, b1v, b2v, norm2, a1v);
+ return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, b1v, b2v, plane2, a1v);
}
else if (b_is_point)
{
// b2 used to be consistent with (degenerated) checks above (is it needed?)
- return collinear_one_degenerted<calc_t>(b, false, a1, a2, b1, b2, a1v, a2v, norm1, b1v);
+ return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, a1v, a2v, plane1, b1v);
}
else
{
@@ -289,16 +409,16 @@ struct relate_spherical_segments
// use shorter segment
if (len1 <= len2)
{
- calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, norm1, b1v, dist_a1_a2, dist_a1_b1);
- calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, norm1, b2v, dist_a1_a2, dist_a1_b2);
+ 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);
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, norm2, a1v, dist_b1_b2, dist_b1_a1);
- calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, norm2, a2v, dist_b1_b2, dist_b1_a2);
+ 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);
dist_a1_a2 = dist_b1_a2 - dist_b1_a1;
dist_a1_b1 = -dist_b1_a1;
dist_a1_b2 = dist_b1_b2 - dist_b1_a1;
@@ -359,7 +479,8 @@ struct relate_spherical_segments
vec3d_t i1;
intersection_point_flag ip_flag;
calc_t dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1;
- if (calculate_ip_data(a1, a2, b1, b2, a1v, a2v, b1v, b2v, norm1, norm2, sides,
+ 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))
{
// intersects
@@ -368,7 +489,7 @@ struct relate_spherical_segments
calc_t,
segment_ratio<calc_t>,
vec3d_t
- > sinfo;
+ > sinfo(calc_policy);
sinfo.robust_ra.assign(dist_a1_i1, dist_a1_a2);
sinfo.robust_rb.assign(dist_b1_i1, dist_b1_b2);
@@ -385,30 +506,32 @@ struct relate_spherical_segments
}
private:
- template <typename CalcT, typename Segment, typename Point1, typename Point2, typename Vec3d>
- static inline return_type collinear_one_degenerted(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& norm,
- Vec3d const& vother)
+ template <typename Policy, typename CalcT, typename Segment, typename Point1, typename Point2, typename Vec3d, typename Plane>
+ static inline typename Policy::return_type
+ 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,
+ Plane const& plane,
+ Vec3d const& vother)
{
CalcT dist_1_2, dist_1_o;
- return ! calculate_collinear_data(a1, a2, b1, b2, v1, v2, norm, vother, dist_1_2, dist_1_o)
+ return ! calculate_collinear_data(a1, a2, b1, b2, v1, v2, plane, vother, dist_1_2, dist_1_o)
? Policy::disjoint()
: Policy::one_degenerate(segment, segment_ratio<CalcT>(dist_1_o, dist_1_2), degenerated_a);
}
- template <typename Point1, typename Point2, typename Vec3d, typename CalcT>
- static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2,
- Point2 const& b1, Point2 const& b2,
- Vec3d const& a1v, // in
- Vec3d const& a2v, // in
- Vec3d const& norm1, // in
- Vec3d const& b1v_or_b2v, // in
+ template <typename Point1, typename Point2, typename Vec3d, typename Plane, typename CalcT>
+ static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2, // in
+ Point2 const& b1, Point2 const& b2, // in
+ 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
{
// calculate dist_a1_a2 and dist_a1_i1
- calculate_dists(a1v, a2v, norm1, b1v_or_b2v, dist_a1_a2, dist_a1_i1);
+ calculate_dists(a1v, a2v, plane1, b1v_or_b2v, dist_a1_a2, 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))
@@ -427,54 +550,53 @@ private:
return segment_ratio<CalcT>(dist_a1_i1, dist_a1_a2).on_segment();
}
- template <typename Point1, typename Point2, typename Vec3d, typename CalcT>
+ template <typename Point1, typename Point2, typename Vec3d, typename Plane, typename CalcT>
static inline bool calculate_ip_data(Point1 const& a1, Point1 const& a2, // in
Point2 const& b1, Point2 const& b2, // in
Vec3d const& a1v, Vec3d const& a2v, // in
Vec3d const& b1v, Vec3d const& b2v, // in
- Vec3d const& norm1, Vec3d const& norm2, // in
- side_info const& sides, // in
- Vec3d & i1, // in-out
- CalcT& dist_a1_a2, CalcT& dist_a1_i1, // out
- CalcT& dist_b1_b2, CalcT& dist_b1_i1, // out
+ Plane const& plane1, // in
+ 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
{
- // great circles intersections
- i1 = cross_product(norm1, norm2);
- // NOTE: the length should be greater than 0 at this point
- // if the normals were not normalized and their dot product
- // not checked before this function is called the length
- // should be checked here (math::equals(len, c0))
- CalcT const len = math::sqrt(dot_product(i1, i1));
- divide_value(i1, len); // normalize i1
-
- calculate_dists(a1v, a2v, norm1, i1, dist_a1_a2, dist_a1_i1);
+ Vec3d ip1, ip2;
+ calc_policy.intersection_points(plane1, plane2, ip1, ip2);
+ calculate_dists(a1v, a2v, plane1, ip1, dist_a1_a2, dist_a1_ip);
+ ip = ip1;
+
// choose the opposite side of the globe if the distance is shorter
{
- CalcT const d = abs_distance(dist_a1_a2, dist_a1_i1);
+ CalcT const d = abs_distance(dist_a1_a2, dist_a1_ip);
if (d > CalcT(0))
{
- CalcT const dist_a1_i2 = dist_of_i2(dist_a1_i1);
+ // TODO: this should be ok not only for sphere
+ // but requires more investigation
+ CalcT const dist_a1_i2 = dist_of_i2(dist_a1_ip);
CalcT const d2 = abs_distance(dist_a1_a2, dist_a1_i2);
if (d2 < d)
{
- dist_a1_i1 = dist_a1_i2;
- multiply_value(i1, CalcT(-1)); // the opposite intersection
+ dist_a1_ip = dist_a1_i2;
+ ip = ip2;
}
}
}
bool is_on_a = false, is_near_a1 = false, is_near_a2 = false;
- if (! is_potentially_crossing(dist_a1_a2, dist_a1_i1, is_on_a, is_near_a1, is_near_a2))
+ if (! is_potentially_crossing(dist_a1_a2, dist_a1_ip, is_on_a, is_near_a1, is_near_a2))
{
return false;
}
- calculate_dists(b1v, b2v, norm2, i1, dist_b1_b2, dist_b1_i1);
+ calculate_dists(b1v, b2v, plane2, ip, dist_b1_b2, 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_i1, is_on_b, is_near_b1, is_near_b2))
+ if (! is_potentially_crossing(dist_b1_b2, dist_b1_ip, is_on_b, is_near_b1, is_near_b2))
{
return false;
}
@@ -485,8 +607,8 @@ private:
{
if (is_near_b1 && equals_point_point(a1, b1))
{
- dist_a1_i1 = 0;
- dist_b1_i1 = 0;
+ dist_a1_ip = 0;
+ dist_b1_ip = 0;
//i1 = a1v;
ip_flag = ipi_at_a1;
return true;
@@ -494,8 +616,8 @@ private:
if (is_near_b2 && equals_point_point(a1, b2))
{
- dist_a1_i1 = 0;
- dist_b1_i1 = dist_b1_b2;
+ dist_a1_ip = 0;
+ dist_b1_ip = dist_b1_b2;
//i1 = a1v;
ip_flag = ipi_at_a1;
return true;
@@ -506,8 +628,8 @@ private:
{
if (is_near_b1 && equals_point_point(a2, b1))
{
- dist_a1_i1 = dist_a1_a2;
- dist_b1_i1 = 0;
+ dist_a1_ip = dist_a1_a2;
+ dist_b1_ip = 0;
//i1 = a2v;
ip_flag = ipi_at_a2;
return true;
@@ -515,8 +637,8 @@ private:
if (is_near_b2 && equals_point_point(a2, b2))
{
- dist_a1_i1 = dist_a1_a2;
- dist_b1_i1 = dist_b1_b2;
+ dist_a1_ip = dist_a1_a2;
+ dist_b1_ip = dist_b1_b2;
//i1 = a2v;
ip_flag = ipi_at_a2;
return true;
@@ -530,7 +652,7 @@ private:
{
if (is_near_b1 && sides.template get<1, 0>() == 0) // b1 wrt a
{
- dist_b1_i1 = 0;
+ dist_b1_ip = 0;
//i1 = b1v;
ip_flag = ipi_at_b1;
return true;
@@ -538,7 +660,7 @@ private:
if (is_near_b2 && sides.template get<1, 1>() == 0) // b2 wrt a
{
- dist_b1_i1 = dist_b1_b2;
+ dist_b1_ip = dist_b1_b2;
//i1 = b2v;
ip_flag = ipi_at_b2;
return true;
@@ -549,7 +671,7 @@ private:
{
if (is_near_a1 && sides.template get<0, 0>() == 0) // a1 wrt b
{
- dist_a1_i1 = 0;
+ dist_a1_ip = 0;
//i1 = a1v;
ip_flag = ipi_at_a1;
return true;
@@ -557,7 +679,7 @@ private:
if (is_near_a2 && sides.template get<0, 1>() == 0) // a2 wrt b
{
- dist_a1_i1 = dist_a1_a2;
+ dist_a1_ip = dist_a1_a2;
//i1 = a2v;
ip_flag = ipi_at_a2;
return true;
@@ -569,24 +691,26 @@ private:
return is_on_a && is_on_b;
}
- template <typename Vec3d, typename CalcT>
- static inline void calculate_dists(Vec3d const& a1v, // in
- Vec3d const& a2v, // in
- Vec3d const& norm1, // in
- Vec3d const& i1, // in
- CalcT& dist_a1_a2, CalcT& dist_a1_i1) // out
+ 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
{
- CalcT const c0 = 0;
+ //CalcT const c0 = 0;
CalcT const c1 = 1;
CalcT const c2 = 2;
CalcT const c4 = 4;
- CalcT cos_a1_a2 = dot_product(a1v, a2v);
+ CalcT cos_a1_a2 = plane1.cos_angle_between(a1v, a2v);
dist_a1_a2 = -cos_a1_a2 + c1; // [1, -1] -> [0, 2] representing [0, pi]
- CalcT cos_a1_i1 = dot_product(a1v, i1);
+ bool is_forward = true;
+ CalcT cos_a1_i1 = plane1.cos_angle_between(a1v, i1, is_forward);
dist_a1_i1 = -cos_a1_i1 + c1; // [0, 2] representing [0, pi]
- if (dot_product(norm1, cross_product(a1v, i1)) < c0) // left or right of a1 on a
+ if (! is_forward) // left or right of a1 on a
{
dist_a1_i1 = -dist_a1_i1; // [0, 2] -> [0, -2] representing [0, -pi]
}
@@ -666,27 +790,117 @@ private:
}
};
+struct spherical_segments_calc_policy
+{
+ template <typename Point, typename Point3d>
+ static Point from_cart3d(Point3d const& point_3d)
+ {
+ return formula::cart3d_to_sph<Point>(point_3d);
+ }
+
+ template <typename Point3d, typename Point>
+ static Point3d to_cart3d(Point const& point)
+ {
+ return formula::sph_to_cart3d<Point3d>(point);
+ }
+
+ template <typename Point3d>
+ struct plane
+ {
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ // not normalized
+ plane(Point3d const& p1, Point3d const& p2)
+ : normal(cross_product(p1, p2))
+ {}
+
+ int side_value(Point3d const& pt) const
+ {
+ return formula::sph_side_value(normal, pt);
+ }
+
+ static coord_t cos_angle_between(Point3d const& p1, Point3d const& p2)
+ {
+ return dot_product(p1, p2);
+ }
+
+ coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const
+ {
+ coord_t const c0 = 0;
+ is_forward = dot_product(normal, cross_product(p1, p2)) >= c0;
+ return dot_product(p1, p2);
+ }
+
+ Point3d normal;
+ };
+
+ template <typename Point3d>
+ static plane<Point3d> get_plane(Point3d const& p1, Point3d const& p2)
+ {
+ return plane<Point3d>(p1, p2);
+ }
+
+ template <typename Point3d>
+ static bool intersection_points(plane<Point3d> const& plane1,
+ plane<Point3d> const& plane2,
+ Point3d & ip1, Point3d & ip2)
+ {
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ ip1 = cross_product(plane1.normal, plane2.normal);
+ // NOTE: the length should be greater than 0 at this point
+ // if the normals were not normalized and their dot product
+ // not checked before this function is called the length
+ // should be checked here (math::equals(len, c0))
+ coord_t const len = math::sqrt(dot_product(ip1, ip1));
+ divide_value(ip1, len); // normalize i1
+
+ ip2 = ip1;
+ multiply_value(ip2, coord_t(-1));
+
+ return true;
+ }
+};
+
+
+template
+<
+ typename CalculationType = void
+>
+struct spherical_segments
+ : ecef_segments
+ <
+ spherical_segments_calc_policy,
+ CalculationType
+ >
+{};
+
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
-/*template <typename Policy, typename CalculationType>
-struct default_strategy<spherical_polar_tag, Policy, CalculationType>
+/*template <typename CalculationType>
+struct default_strategy<spherical_polar_tag, CalculationType>
{
- typedef relate_spherical_segments<Policy, CalculationType> type;
+ typedef spherical_segments<CalculationType> type;
};*/
-template <typename Policy, typename CalculationType>
-struct default_strategy<spherical_equatorial_tag, Policy, CalculationType>
+template <typename CalculationType>
+struct default_strategy<spherical_equatorial_tag, CalculationType>
{
- typedef relate_spherical_segments<Policy, CalculationType> type;
+ typedef spherical_segments<CalculationType> type;
};
-template <typename Policy, typename CalculationType>
-struct default_strategy<geographic_tag, Policy, CalculationType>
+template <typename CalculationType>
+struct default_strategy<geographic_tag, CalculationType>
{
- typedef relate_spherical_segments<Policy, CalculationType> type;
+ // NOTE: Spherical strategy returns the same result as the geographic one
+ // representing segments as great elliptic arcs. If the elliptic arcs are
+ // not great elliptic arcs (the origin not in the center of the coordinate
+ // system) then there may be problems with consistency of the side and
+ // intersection strategies.
+ typedef spherical_segments<CalculationType> type;
};
} // namespace services
@@ -695,6 +909,71 @@ struct default_strategy<geographic_tag, Policy, CalculationType>
}} // namespace strategy::intersection
+
+namespace strategy
+{
+
+namespace within { namespace services
+{
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, linear_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, polygonal_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, linear_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, polygonal_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+}} // within::services
+
+namespace covered_by { namespace services
+{
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, linear_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, polygonal_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, linear_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, polygonal_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+}} // within::services
+
+} // strategy
+
+
}} // namespace boost::geometry
diff --git a/boost/geometry/strategies/strategies.hpp b/boost/geometry/strategies/strategies.hpp
index 342485cc4c..f3c6787a4b 100644
--- a/boost/geometry/strategies/strategies.hpp
+++ b/boost/geometry/strategies/strategies.hpp
@@ -4,9 +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 2014-2016.
-// Modifications copyright (c) 2014-2016 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 Vissarion Fysikopoulos, 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
@@ -23,18 +24,24 @@
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/strategies/area.hpp>
+#include <boost/geometry/strategies/azimuth.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/strategies/convex_hull.hpp>
+#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/disjoint.hpp>
#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/envelope.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_strategies.hpp> // for backward compatibility
+#include <boost/geometry/strategies/relate.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/transform.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/strategies/cartesian/area_surveyor.hpp>
+#include <boost/geometry/strategies/cartesian/azimuth.hpp>
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
#include <boost/geometry/strategies/cartesian/buffer_end_flat.hpp>
#include <boost/geometry/strategies/cartesian/buffer_end_round.hpp>
@@ -47,30 +54,42 @@
#include <boost/geometry/strategies/cartesian/centroid_average.hpp>
#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>
#include <boost/geometry/strategies/cartesian/centroid_weighted_length.hpp>
+#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp>
#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
#include <boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
+#include <boost/geometry/strategies/cartesian/intersection.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
-#include <boost/geometry/strategies/spherical/area_huiller.hpp>
+#include <boost/geometry/strategies/spherical/area.hpp>
+#include <boost/geometry/strategies/spherical/azimuth.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>
#include <boost/geometry/strategies/spherical/compare_circular.hpp>
+#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
#include <boost/geometry/strategies/spherical/intersection.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
+#include <boost/geometry/strategies/geographic/area.hpp>
+#include <boost/geometry/strategies/geographic/azimuth.hpp>
+#include <boost/geometry/strategies/geographic/distance.hpp>
#include <boost/geometry/strategies/geographic/distance_andoyer.hpp>
#include <boost/geometry/strategies/geographic/distance_thomas.hpp>
#include <boost/geometry/strategies/geographic/distance_vincenty.hpp>
-//#include <boost/geometry/strategies/geographic/side_andoyer.hpp>
-//#include <boost/geometry/strategies/geographic/side_thomas.hpp>
-//#include <boost/geometry/strategies/geographic/side_vincenty.hpp>
+#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
+#include <boost/geometry/strategies/geographic/intersection.hpp>
+//#include <boost/geometry/strategies/geographic/intersection_elliptic.hpp>
+#include <boost/geometry/strategies/geographic/side.hpp>
+#include <boost/geometry/strategies/geographic/side_andoyer.hpp>
+#include <boost/geometry/strategies/geographic/side_thomas.hpp>
+#include <boost/geometry/strategies/geographic/side_vincenty.hpp>
#include <boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp>
#include <boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp>
@@ -80,8 +99,6 @@
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp>
-#include <boost/geometry/strategies/agnostic/relate.hpp>
-
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
diff --git a/boost/geometry/strategies/transform/inverse_transformer.hpp b/boost/geometry/strategies/transform/inverse_transformer.hpp
index e64a46e4a8..5213bce47a 100644
--- a/boost/geometry/strategies/transform/inverse_transformer.hpp
+++ b/boost/geometry/strategies/transform/inverse_transformer.hpp
@@ -14,15 +14,8 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
-// Remove the ublas checking, otherwise the inverse might fail
-// (while nothing seems to be wrong)
-#ifdef BOOST_UBLAS_TYPE_CHECK
-#undef BOOST_UBLAS_TYPE_CHECK
-#endif
-#define BOOST_UBLAS_TYPE_CHECK 0
-
-#include <boost/numeric/ublas/lu.hpp>
-#include <boost/numeric/ublas/io.hpp>
+#include <boost/qvm/mat.hpp>
+#include <boost/qvm/mat_operations.hpp>
#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
@@ -44,31 +37,13 @@ template
std::size_t Dimension2
>
class inverse_transformer
- : public ublas_transformer<CalculationType, Dimension1, Dimension2>
+ : public matrix_transformer<CalculationType, Dimension1, Dimension2>
{
public :
template <typename Transformer>
inline inverse_transformer(Transformer const& input)
{
- typedef boost::numeric::ublas::matrix<CalculationType> matrix_type;
-
- // create a working copy of the input
- matrix_type copy(input.matrix());
-
- // create a permutation matrix for the LU-factorization
- typedef boost::numeric::ublas::permutation_matrix<> permutation_matrix;
- permutation_matrix pm(copy.size1());
-
- // perform LU-factorization
- int res = boost::numeric::ublas::lu_factorize<matrix_type>(copy, pm);
- if( res == 0 )
- {
- // create identity matrix
- this->m_matrix.assign(boost::numeric::ublas::identity_matrix<CalculationType>(copy.size1()));
-
- // backsubstitute to get the inverse
- boost::numeric::ublas::lu_substitute(copy, pm, this->m_matrix);
- }
+ this->m_matrix = boost::qvm::inverse(input.matrix());
}
};
diff --git a/boost/geometry/strategies/transform/map_transformer.hpp b/boost/geometry/strategies/transform/map_transformer.hpp
index 1109e814b9..01ea6168c5 100644
--- a/boost/geometry/strategies/transform/map_transformer.hpp
+++ b/boost/geometry/strategies/transform/map_transformer.hpp
@@ -46,9 +46,10 @@ template
bool SameScale = true
>
class map_transformer
- : public ublas_transformer<CalculationType, Dimension1, Dimension2>
+ : public matrix_transformer<CalculationType, Dimension1, Dimension2>
{
- typedef boost::numeric::ublas::matrix<CalculationType> M;
+ typedef boost::qvm::mat<CalculationType, Dimension1 + 1, Dimension2 + 1> M;
+ typedef boost::qvm::mat<CalculationType, 3, 3> matrix33;
public :
template <typename B, typename D>
@@ -76,26 +77,26 @@ private :
{
// Translate to a coordinate system centered on world coordinates (-wx, -wy)
- M t1(3,3);
- t1(0,0) = 1; t1(0,1) = 0; t1(0,2) = -wx;
- t1(1,0) = 0; t1(1,1) = 1; t1(1,2) = -wy;
- t1(2,0) = 0; t1(2,1) = 0; t1(2,2) = 1;
+ matrix33 t1;
+ qvm::A<0,0>(t1) = 1; qvm::A<0,1>(t1) = 0; qvm::A<0,2>(t1) = -wx;
+ qvm::A<1,0>(t1) = 0; qvm::A<1,1>(t1) = 1; qvm::A<1,2>(t1) = -wy;
+ qvm::A<2,0>(t1) = 0; qvm::A<2,1>(t1) = 0; qvm::A<2,2>(t1) = 1;
// Scale the map
- M s(3,3);
- s(0,0) = scalex; s(0,1) = 0; s(0,2) = 0;
- s(1,0) = 0; s(1,1) = scaley; s(1,2) = 0;
- s(2,0) = 0; s(2,1) = 0; s(2,2) = 1;
+ matrix33 s;
+ qvm::A<0,0>(s) = scalex; qvm::A<0,1>(s) = 0; qvm::A<0,2>(s) = 0;
+ qvm::A<1,0>(s) = 0; qvm::A<1,1>(s) = scaley; qvm::A<1,2>(s) = 0;
+ qvm::A<2,0>(s) = 0; qvm::A<2,1>(s) = 0; qvm::A<2,2>(s) = 1;
// Translate to a coordinate system centered on the specified pixels (+px, +py)
- M t2(3, 3);
- t2(0,0) = 1; t2(0,1) = 0; t2(0,2) = px;
- t2(1,0) = 0; t2(1,1) = 1; t2(1,2) = py;
- t2(2,0) = 0; t2(2,1) = 0; t2(2,2) = 1;
+ matrix33 t2;
+ qvm::A<0,0>(t2) = 1; qvm::A<0,1>(t2) = 0; qvm::A<0,2>(t2) = px;
+ qvm::A<1,0>(t2) = 0; qvm::A<1,1>(t2) = 1; qvm::A<1,2>(t2) = py;
+ qvm::A<2,0>(t2) = 0; qvm::A<2,1>(t2) = 0; qvm::A<2,2>(t2) = 1;
// Calculate combination matrix in two steps
- this->m_matrix = boost::numeric::ublas::prod(s, t1);
- this->m_matrix = boost::numeric::ublas::prod(t2, this->m_matrix);
+ this->m_matrix = s * t1;
+ this->m_matrix = t2 * this->m_matrix;
}
@@ -140,20 +141,20 @@ private :
if (Mirror)
{
// Mirror in y-direction
- M m(3,3);
- m(0,0) = 1; m(0,1) = 0; m(0,2) = 0;
- m(1,0) = 0; m(1,1) = -1; m(1,2) = 0;
- m(2,0) = 0; m(2,1) = 0; m(2,2) = 1;
+ matrix33 m;
+ qvm::A<0,0>(m) = 1; qvm::A<0,1>(m) = 0; qvm::A<0,2>(m) = 0;
+ qvm::A<1,0>(m) = 0; qvm::A<1,1>(m) = -1; qvm::A<1,2>(m) = 0;
+ qvm::A<2,0>(m) = 0; qvm::A<2,1>(m) = 0; qvm::A<2,2>(m) = 1;
// Translate in y-direction such that it fits again
- M y(3, 3);
- y(0,0) = 1; y(0,1) = 0; y(0,2) = 0;
- y(1,0) = 0; y(1,1) = 1; y(1,2) = height;
- y(2,0) = 0; y(2,1) = 0; y(2,2) = 1;
+ matrix33 y;
+ qvm::A<0,0>(y) = 1; qvm::A<0,1>(y) = 0; qvm::A<0,2>(y) = 0;
+ qvm::A<1,0>(y) = 0; qvm::A<1,1>(y) = 1; qvm::A<1,2>(y) = height;
+ qvm::A<2,0>(y) = 0; qvm::A<2,1>(y) = 0; qvm::A<2,2>(y) = 1;
// Calculate combination matrix in two steps
- this->m_matrix = boost::numeric::ublas::prod(m, this->m_matrix);
- this->m_matrix = boost::numeric::ublas::prod(y, this->m_matrix);
+ this->m_matrix = m * this->m_matrix;
+ this->m_matrix = y * this->m_matrix;
}
}
};
diff --git a/boost/geometry/strategies/transform/matrix_transformers.hpp b/boost/geometry/strategies/transform/matrix_transformers.hpp
index d891263a7d..e0ac6496f3 100644
--- a/boost/geometry/strategies/transform/matrix_transformers.hpp
+++ b/boost/geometry/strategies/transform/matrix_transformers.hpp
@@ -22,27 +22,9 @@
#include <cstddef>
-// Remove the ublas checking, otherwise the inverse might fail
-// (while nothing seems to be wrong)
-#ifdef BOOST_UBLAS_TYPE_CHECK
-#undef BOOST_UBLAS_TYPE_CHECK
-#endif
-#define BOOST_UBLAS_TYPE_CHECK 0
-
-#include <boost/numeric/conversion/cast.hpp>
-
-#if defined(__clang__)
-// Avoid warning about unused UBLAS function: boost_numeric_ublas_abs
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-function"
-#endif
-
-#include <boost/numeric/ublas/vector.hpp>
-#include <boost/numeric/ublas/matrix.hpp>
-
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
+#include <boost/qvm/mat.hpp>
+#include <boost/qvm/mat_access.hpp>
+#include <boost/qvm/mat_operations.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
@@ -75,38 +57,37 @@ template
std::size_t Dimension1,
std::size_t Dimension2
>
-class ublas_transformer
+class matrix_transformer
{
};
template <typename CalculationType>
-class ublas_transformer<CalculationType, 2, 2>
+class matrix_transformer<CalculationType, 2, 2>
{
protected :
typedef CalculationType ct;
- typedef boost::numeric::ublas::matrix<ct> matrix_type;
+ typedef boost::qvm::mat<ct, 3, 3> matrix_type;
matrix_type m_matrix;
public :
- inline ublas_transformer(
+ inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
- : m_matrix(3, 3)
{
- m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2;
- m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2;
- m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2;
+ qvm::A<0,0>(m_matrix) = m_0_0; qvm::A<0,1>(m_matrix) = m_0_1; qvm::A<0,2>(m_matrix) = m_0_2;
+ qvm::A<1,0>(m_matrix) = m_1_0; qvm::A<1,1>(m_matrix) = m_1_1; qvm::A<1,2>(m_matrix) = m_1_2;
+ qvm::A<2,0>(m_matrix) = m_2_0; qvm::A<2,1>(m_matrix) = m_2_1; qvm::A<2,2>(m_matrix) = m_2_2;
}
- inline ublas_transformer(matrix_type const& matrix)
+ inline matrix_transformer(matrix_type const& matrix)
: m_matrix(matrix)
{}
- inline ublas_transformer() : m_matrix(3, 3) {}
+ inline matrix_transformer() {}
template <typename P1, typename P2>
inline bool apply(P1 const& p1, P2& p2) const
@@ -117,8 +98,8 @@ public :
ct const& c1 = get<0>(p1);
ct const& c2 = get<1>(p1);
- ct p2x = c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + m_matrix(0,2);
- ct p2y = c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + m_matrix(1,2);
+ ct p2x = c1 * qvm::A<0,0>(m_matrix) + c2 * qvm::A<0,1>(m_matrix) + qvm::A<0,2>(m_matrix);
+ ct p2y = c1 * qvm::A<1,0>(m_matrix) + c2 * qvm::A<1,1>(m_matrix) + qvm::A<1,2>(m_matrix);
typedef typename geometry::coordinate_type<P2>::type ct2;
set<0>(p2, boost::numeric_cast<ct2>(p2x));
@@ -133,51 +114,50 @@ public :
// It IS possible to go from 3 to 2 coordinates
template <typename CalculationType>
-class ublas_transformer<CalculationType, 3, 2> : public ublas_transformer<CalculationType, 2, 2>
+class matrix_transformer<CalculationType, 3, 2> : public matrix_transformer<CalculationType, 2, 2>
{
typedef CalculationType ct;
public :
- inline ublas_transformer(
+ inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
- : ublas_transformer<CalculationType, 2, 2>(
+ : matrix_transformer<CalculationType, 2, 2>(
m_0_0, m_0_1, m_0_2,
m_1_0, m_1_1, m_1_2,
m_2_0, m_2_1, m_2_2)
{}
- inline ublas_transformer()
- : ublas_transformer<CalculationType, 2, 2>()
+ inline matrix_transformer()
+ : matrix_transformer<CalculationType, 2, 2>()
{}
};
template <typename CalculationType>
-class ublas_transformer<CalculationType, 3, 3>
+class matrix_transformer<CalculationType, 3, 3>
{
protected :
typedef CalculationType ct;
- typedef boost::numeric::ublas::matrix<ct> matrix_type;
+ typedef boost::qvm::mat<ct, 4, 4> matrix_type;
matrix_type m_matrix;
public :
- inline ublas_transformer(
+ inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2, ct const& m_0_3,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2, ct const& m_1_3,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2, ct const& m_2_3,
ct const& m_3_0, ct const& m_3_1, ct const& m_3_2, ct const& m_3_3
)
- : m_matrix(4, 4)
{
- m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2; m_matrix(0,3) = m_0_3;
- m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2; m_matrix(1,3) = m_1_3;
- m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2; m_matrix(2,3) = m_2_3;
- m_matrix(3,0) = m_3_0; m_matrix(3,1) = m_3_1; m_matrix(3,2) = m_3_2; m_matrix(3,3) = m_3_3;
+ qvm::A<0,0>(m_matrix) = m_0_0; qvm::A<0,1>(m_matrix) = m_0_1; qvm::A<0,2>(m_matrix) = m_0_2; qvm::A<0,3>(m_matrix) = m_0_3;
+ qvm::A<1,0>(m_matrix) = m_1_0; qvm::A<1,1>(m_matrix) = m_1_1; qvm::A<1,2>(m_matrix) = m_1_2; qvm::A<1,3>(m_matrix) = m_1_3;
+ qvm::A<2,0>(m_matrix) = m_2_0; qvm::A<2,1>(m_matrix) = m_2_1; qvm::A<2,2>(m_matrix) = m_2_2; qvm::A<2,3>(m_matrix) = m_2_3;
+ qvm::A<3,0>(m_matrix) = m_3_0; qvm::A<3,1>(m_matrix) = m_3_1; qvm::A<3,2>(m_matrix) = m_3_2; qvm::A<3,3>(m_matrix) = m_3_3;
}
- inline ublas_transformer() : m_matrix(4, 4) {}
+ inline matrix_transformer() {}
template <typename P1, typename P2>
inline bool apply(P1 const& p1, P2& p2) const
@@ -222,7 +202,7 @@ class translate_transformer
template<typename CalculationType>
-class translate_transformer<CalculationType, 2, 2> : public ublas_transformer<CalculationType, 2, 2>
+class translate_transformer<CalculationType, 2, 2> : public matrix_transformer<CalculationType, 2, 2>
{
public :
// To have translate transformers compatible for 2/3 dimensions, the
@@ -230,7 +210,7 @@ public :
inline translate_transformer(CalculationType const& translate_x,
CalculationType const& translate_y,
CalculationType const& = 0)
- : ublas_transformer<CalculationType, 2, 2>(
+ : matrix_transformer<CalculationType, 2, 2>(
1, 0, translate_x,
0, 1, translate_y,
0, 0, 1)
@@ -239,13 +219,13 @@ public :
template <typename CalculationType>
-class translate_transformer<CalculationType, 3, 3> : public ublas_transformer<CalculationType, 3, 3>
+class translate_transformer<CalculationType, 3, 3> : public matrix_transformer<CalculationType, 3, 3>
{
public :
inline translate_transformer(CalculationType const& translate_x,
CalculationType const& translate_y,
CalculationType const& translate_z)
- : ublas_transformer<CalculationType, 3, 3>(
+ : matrix_transformer<CalculationType, 3, 3>(
1, 0, 0, translate_x,
0, 1, 0, translate_y,
0, 0, 1, translate_z,
@@ -275,14 +255,14 @@ class scale_transformer
template <typename CalculationType>
-class scale_transformer<CalculationType, 2, 2> : public ublas_transformer<CalculationType, 2, 2>
+class scale_transformer<CalculationType, 2, 2> : public matrix_transformer<CalculationType, 2, 2>
{
public :
inline scale_transformer(CalculationType const& scale_x,
CalculationType const& scale_y,
CalculationType const& = 0)
- : ublas_transformer<CalculationType, 2, 2>(
+ : matrix_transformer<CalculationType, 2, 2>(
scale_x, 0, 0,
0, scale_y, 0,
0, 0, 1)
@@ -290,7 +270,7 @@ public :
inline scale_transformer(CalculationType const& scale)
- : ublas_transformer<CalculationType, 2, 2>(
+ : matrix_transformer<CalculationType, 2, 2>(
scale, 0, 0,
0, scale, 0,
0, 0, 1)
@@ -299,13 +279,13 @@ public :
template <typename CalculationType>
-class scale_transformer<CalculationType, 3, 3> : public ublas_transformer<CalculationType, 3, 3>
+class scale_transformer<CalculationType, 3, 3> : public matrix_transformer<CalculationType, 3, 3>
{
public :
inline scale_transformer(CalculationType const& scale_x,
CalculationType const& scale_y,
CalculationType const& scale_z)
- : ublas_transformer<CalculationType, 3, 3>(
+ : matrix_transformer<CalculationType, 3, 3>(
scale_x, 0, 0, 0,
0, scale_y, 0, 0,
0, 0, scale_z, 0,
@@ -314,7 +294,7 @@ public :
inline scale_transformer(CalculationType const& scale)
- : ublas_transformer<CalculationType, 3, 3>(
+ : matrix_transformer<CalculationType, 3, 3>(
scale, 0, 0, 0,
0, scale, 0, 0,
0, 0, scale, 0,
@@ -363,11 +343,11 @@ template
std::size_t Dimension2
>
class rad_rotate_transformer
- : public ublas_transformer<CalculationType, Dimension1, Dimension2>
+ : public matrix_transformer<CalculationType, Dimension1, Dimension2>
{
public :
inline rad_rotate_transformer(CalculationType const& angle)
- : ublas_transformer<CalculationType, Dimension1, Dimension2>(
+ : matrix_transformer<CalculationType, Dimension1, Dimension2>(
cos(angle), sin(angle), 0,
-sin(angle), cos(angle), 0,
0, 0, 1)
diff --git a/boost/geometry/strategies/within.hpp b/boost/geometry/strategies/within.hpp
index d625bc40e6..28a3283db0 100644
--- a/boost/geometry/strategies/within.hpp
+++ b/boost/geometry/strategies/within.hpp
@@ -4,6 +4,11 @@
// 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.
@@ -16,6 +21,12 @@
#include <boost/mpl/assert.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+
namespace boost { namespace geometry
{
@@ -30,23 +41,39 @@ namespace services
/*!
\brief Traits class binding a within determination strategy to a coordinate system
\ingroup within
-\tparam TagContained tag (possibly casted) of point-type
-\tparam TagContained tag (possibly casted) of (possibly) containing type
-\tparam CsTagContained tag of coordinate system of point-type
-\tparam CsTagContaining tag of coordinate system of (possibly) containing type
-\tparam Geometry geometry-type of input (often point, or box)
+\tparam GeometryContained geometry-type of input (possibly) contained type
\tparam GeometryContaining geometry-type of input (possibly) containing type
+\tparam TagContained casted tag of (possibly) contained type
+\tparam TagContaining casted tag of (possibly) containing type
+\tparam CsTagContained tag of coordinate system of (possibly) contained type
+\tparam CsTagContaining tag of coordinate system of (possibly) containing type
*/
template
<
- typename TagContained,
- typename TagContaining,
- typename CastedTagContained,
- typename CastedTagContaining,
- typename CsTagContained,
- typename CsTagContaining,
typename GeometryContained,
- typename GeometryContaining
+ typename GeometryContaining,
+ typename TagContained = typename tag<GeometryContained>::type,
+ typename TagContaining = typename tag<GeometryContaining>::type,
+ typename CastedTagContained = typename tag_cast
+ <
+ typename tag<GeometryContained>::type,
+ pointlike_tag, linear_tag, polygonal_tag, areal_tag
+ >::type,
+ typename CastedTagContaining = typename tag_cast
+ <
+ typename tag<GeometryContaining>::type,
+ pointlike_tag, linear_tag, polygonal_tag, areal_tag
+ >::type,
+ typename CsTagContained = typename tag_cast
+ <
+ typename cs_tag<typename point_type<GeometryContained>::type>::type,
+ spherical_tag
+ >::type,
+ typename CsTagContaining = typename tag_cast
+ <
+ typename cs_tag<typename point_type<GeometryContaining>::type>::type,
+ spherical_tag
+ >::type
>
struct default_strategy
{
diff --git a/boost/geometry/util/math.hpp b/boost/geometry/util/math.hpp
index 234cfa1ed0..b1c3648c98 100644
--- a/boost/geometry/util/math.hpp
+++ b/boost/geometry/util/math.hpp
@@ -71,6 +71,19 @@ inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4, T c
}
+template <typename T>
+inline T bounded(T const& v, T const& lower, T const& upper)
+{
+ return (std::min)((std::max)(v, lower), upper);
+}
+
+template <typename T>
+inline T bounded(T const& v, T const& lower)
+{
+ return (std::max)(v, lower);
+}
+
+
template <typename T,
bool IsFloatingPoint = boost::is_floating_point<T>::value>
struct abs
@@ -518,7 +531,7 @@ inline T scaled_epsilon(T const& value)
}
-// Maybe replace this by boost equals or boost ublas numeric equals or so
+// Maybe replace this by boost equals or so
/*!
\brief returns true if both arguments are equal.
diff --git a/boost/geometry/util/normalize_spheroidal_coordinates.hpp b/boost/geometry/util/normalize_spheroidal_coordinates.hpp
index 377051eef1..19d4d33d28 100644
--- a/boost/geometry/util/normalize_spheroidal_coordinates.hpp
+++ b/boost/geometry/util/normalize_spheroidal_coordinates.hpp
@@ -282,6 +282,40 @@ inline CoordinateType longitude_distance_unsigned(CoordinateType const& longitud
return diff;
}
+/*!
+\brief The abs difference between longitudes in range [0, 180].
+\tparam Units The units of the coordindate system in the spheroid
+\tparam CoordinateType The type of the coordinates
+\param longitude1 Longitude 1
+\param longitude2 Longitude 2
+\ingroup utility
+*/
+template <typename Units, typename CoordinateType>
+inline CoordinateType longitude_difference(CoordinateType const& longitude1,
+ CoordinateType const& longitude2)
+{
+ return math::abs(math::longitude_distance_signed<Units>(longitude1, longitude2));
+}
+
+template <typename Units, typename CoordinateType>
+inline CoordinateType longitude_interval_distance_signed(CoordinateType const& longitude_a1,
+ CoordinateType const& longitude_a2,
+ CoordinateType const& longitude_b)
+{
+ CoordinateType const c0 = 0;
+ CoordinateType dist_a12 = longitude_distance_signed<Units>(longitude_a1, longitude_a2);
+ CoordinateType dist_a1b = longitude_distance_signed<Units>(longitude_a1, longitude_b);
+ if (dist_a12 < c0)
+ {
+ dist_a12 = -dist_a12;
+ dist_a1b = -dist_a1b;
+ }
+
+ return dist_a1b < c0 ? dist_a1b
+ : dist_a1b > dist_a12 ? dist_a1b - dist_a12
+ : c0;
+}
+
} // namespace math
diff --git a/boost/hana.hpp b/boost/hana.hpp
index 0739e5e05d..2e30810b1b 100644
--- a/boost/hana.hpp
+++ b/boost/hana.hpp
@@ -3,7 +3,7 @@
Includes all the library components except the adapters for external
libraries.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/accessors.hpp b/boost/hana/accessors.hpp
index 06cd46b59d..28204b6e31 100644
--- a/boost/hana/accessors.hpp
+++ b/boost/hana/accessors.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::accessors`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/adapt_adt.hpp b/boost/hana/adapt_adt.hpp
index 46d39eeefc..0bf73467ac 100644
--- a/boost/hana/adapt_adt.hpp
+++ b/boost/hana/adapt_adt.hpp
@@ -2,7 +2,7 @@
@file
Defines the `BOOST_HANA_ADAPT_ADT` macro.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/adapt_struct.hpp b/boost/hana/adapt_struct.hpp
index 85aa2f7f53..c156f44d40 100644
--- a/boost/hana/adapt_struct.hpp
+++ b/boost/hana/adapt_struct.hpp
@@ -2,7 +2,7 @@
@file
Defines the `BOOST_HANA_ADAPT_STRUCT` macro.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/adjust.hpp b/boost/hana/adjust.hpp
index c5e2c7d3f5..e8bab2cac3 100644
--- a/boost/hana/adjust.hpp
+++ b/boost/hana/adjust.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::adjust`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/adjust_if.hpp b/boost/hana/adjust_if.hpp
index 6c1e4786fd..8669009a9a 100644
--- a/boost/hana/adjust_if.hpp
+++ b/boost/hana/adjust_if.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::adjust_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/all.hpp b/boost/hana/all.hpp
index 84912928e9..bc952c986f 100644
--- a/boost/hana/all.hpp
+++ b/boost/hana/all.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::all`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/all_of.hpp b/boost/hana/all_of.hpp
index ade2624d9e..5aff4a01e7 100644
--- a/boost/hana/all_of.hpp
+++ b/boost/hana/all_of.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::all_of`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/and.hpp b/boost/hana/and.hpp
index a883ac9bad..df460d32a6 100644
--- a/boost/hana/and.hpp
+++ b/boost/hana/and.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::and_`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/any.hpp b/boost/hana/any.hpp
index 48670fb50b..9141a758df 100644
--- a/boost/hana/any.hpp
+++ b/boost/hana/any.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::any`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/any_of.hpp b/boost/hana/any_of.hpp
index 1dd1cde9be..59c130e54d 100644
--- a/boost/hana/any_of.hpp
+++ b/boost/hana/any_of.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::any_of`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -62,12 +62,12 @@ BOOST_HANA_NAMESPACE_BEGIN
struct any_of_helper {
template <typename Xs, typename Pred>
static constexpr auto apply(bool prev_cond, Xs&& xs, Pred&& pred) {
- auto cond = hana::if_(pred(hana::at_c<k>(xs)), hana::true_c,
- hana::false_c);
return prev_cond ? hana::true_c
- : any_of_impl::any_of_helper<k + 1, Len>::apply(cond,
- static_cast<Xs&&>(xs),
- static_cast<Pred&&>(pred));
+ : any_of_impl::any_of_helper<k + 1, Len>::apply(
+ hana::if_(pred(hana::at_c<k>(xs)), hana::true_c, hana::false_c),
+ static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred)
+ );
}
template <typename Xs, typename Pred>
@@ -108,13 +108,14 @@ BOOST_HANA_NAMESPACE_BEGIN
>> {
template <typename Xs, typename Pred>
static constexpr auto lazy_any_of_helper(hana::false_, bool prev_cond, Xs&& xs, Pred&& pred) {
- auto cond = hana::if_(pred(hana::front(xs)), hana::true_c, hana::false_c);
decltype(auto) tail = hana::drop_front(static_cast<Xs&&>(xs));
constexpr bool done = decltype(hana::is_empty(tail))::value;
return prev_cond ? hana::true_c
- : lazy_any_of_helper(hana::bool_c<done>, cond,
- static_cast<decltype(tail)&&>(tail),
- static_cast<Pred&&>(pred));
+ : lazy_any_of_helper(hana::bool_<done>{},
+ hana::if_(pred(hana::front(xs)), hana::true_{}, hana::false_{}),
+ static_cast<decltype(tail)&&>(tail),
+ static_cast<Pred&&>(pred)
+ );
}
template <typename Xs, typename Pred>
@@ -123,11 +124,12 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename Xs, typename Pred>
static constexpr auto lazy_any_of_helper(hana::false_, hana::false_, Xs&& xs, Pred&& pred) {
- auto cond = hana::if_(pred(hana::front(xs)), hana::true_c, hana::false_c);
constexpr bool done = decltype(hana::is_empty(hana::drop_front(xs)))::value;
- return lazy_any_of_helper(hana::bool_c<done>, cond,
- hana::drop_front(static_cast<Xs&&>(xs)),
- static_cast<Pred&&>(pred));
+ return lazy_any_of_helper(hana::bool_c<done>,
+ hana::if_(pred(hana::front(xs)), hana::true_c, hana::false_c),
+ hana::drop_front(static_cast<Xs&&>(xs)),
+ static_cast<Pred&&>(pred)
+ );
}
template <typename Cond, typename Xs, typename Pred>
diff --git a/boost/hana/ap.hpp b/boost/hana/ap.hpp
index a344244090..a96f7d1aa7 100644
--- a/boost/hana/ap.hpp
+++ b/boost/hana/ap.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::ap`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/append.hpp b/boost/hana/append.hpp
index 6c4cf4d02f..951f24d35e 100644
--- a/boost/hana/append.hpp
+++ b/boost/hana/append.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::append`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/assert.hpp b/boost/hana/assert.hpp
index c529770474..e746910515 100644
--- a/boost/hana/assert.hpp
+++ b/boost/hana/assert.hpp
@@ -2,7 +2,7 @@
@file
Defines macros to perform different kinds of assertions.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/at.hpp b/boost/hana/at.hpp
index 86cab698c4..c3f158b0ff 100644
--- a/boost/hana/at.hpp
+++ b/boost/hana/at.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::at` and `boost::hana::at_c`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/at_key.hpp b/boost/hana/at_key.hpp
index af8d5a603a..74d45d6d56 100644
--- a/boost/hana/at_key.hpp
+++ b/boost/hana/at_key.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::at_key`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/back.hpp b/boost/hana/back.hpp
index 76efcf7717..4fed83f032 100644
--- a/boost/hana/back.hpp
+++ b/boost/hana/back.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::back`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/basic_tuple.hpp b/boost/hana/basic_tuple.hpp
index 8651e464bf..dbc762fb1b 100644
--- a/boost/hana/basic_tuple.hpp
+++ b/boost/hana/basic_tuple.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::basic_tuple`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -14,7 +14,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
-#include <boost/hana/detail/intrinsics.hpp>
+#include <boost/hana/detail/ebo.hpp>
#include <boost/hana/fwd/at.hpp>
#include <boost/hana/fwd/bool.hpp>
#include <boost/hana/fwd/concept/sequence.hpp>
@@ -38,79 +38,10 @@ Distributed under the Boost Software License, Version 1.0.
BOOST_HANA_NAMESPACE_BEGIN
namespace detail {
//////////////////////////////////////////////////////////////////////
- // elt<n, Xn>
- //
- // `elt` stands for `tuple_element`; the name is compressed to reduce
- // symbol lengths.
- //
- // Wrapper holding the actual elements of a tuple. It takes care of
- // optimizing the storage for empty types.
- //
- // When available, we use compiler intrinsics to reduce the number
- // of instantiations.
- //////////////////////////////////////////////////////////////////////
- template <std::size_t n, typename Xn, bool =
- BOOST_HANA_TT_IS_EMPTY(Xn) && !BOOST_HANA_TT_IS_FINAL(Xn)
- >
- struct elt;
-
- // Specialize storage for empty types
- template <std::size_t n, typename Xn>
- struct elt<n, Xn, true> : Xn {
- constexpr elt() = default;
-
- template <typename Yn>
- explicit constexpr elt(Yn&& yn)
- : Xn(static_cast<Yn&&>(yn))
- { }
- };
-
- // Specialize storage for non-empty types
- template <std::size_t n, typename Xn>
- struct elt<n, Xn, false> {
- constexpr elt() = default;
-
- template <typename Yn>
- explicit constexpr elt(Yn&& yn)
- : data_(static_cast<Yn&&>(yn))
- { }
-
- Xn data_;
- };
- }
-
- //////////////////////////////////////////////////////////////////////////
- // get_impl
- //////////////////////////////////////////////////////////////////////////
- template <std::size_t n, typename Xn>
- constexpr Xn const& get_impl(detail::elt<n, Xn, true> const& xn)
- { return xn; }
-
- template <std::size_t n, typename Xn>
- constexpr Xn& get_impl(detail::elt<n, Xn, true>& xn)
- { return xn; }
-
- template <std::size_t n, typename Xn>
- constexpr Xn&& get_impl(detail::elt<n, Xn, true>&& xn)
- { return static_cast<Xn&&>(xn); }
-
-
- template <std::size_t n, typename Xn>
- constexpr Xn const& get_impl(detail::elt<n, Xn, false> const& xn)
- { return xn.data_; }
-
- template <std::size_t n, typename Xn>
- constexpr Xn& get_impl(detail::elt<n, Xn, false>& xn)
- { return xn.data_; }
-
- template <std::size_t n, typename Xn>
- constexpr Xn&& get_impl(detail::elt<n, Xn, false>&& xn)
- { return static_cast<Xn&&>(xn.data_); }
-
- namespace detail {
- //////////////////////////////////////////////////////////////////////
// basic_tuple_impl<n, Xn>
//////////////////////////////////////////////////////////////////////
+ template <std::size_t> struct bti; // basic_tuple_index
+
struct from_other { };
template <typename Indices, typename ...Xn>
@@ -118,7 +49,7 @@ BOOST_HANA_NAMESPACE_BEGIN
template <std::size_t ...n, typename ...Xn>
struct basic_tuple_impl<std::index_sequence<n...>, Xn...>
- : detail::elt<n, Xn>...
+ : detail::ebo<bti<n>, Xn>...
{
static constexpr std::size_t size_ = sizeof...(Xn);
@@ -126,12 +57,12 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename Other>
explicit constexpr basic_tuple_impl(detail::from_other, Other&& other)
- : detail::elt<n, Xn>(get_impl<n>(static_cast<Other&&>(other)))...
+ : detail::ebo<bti<n>, Xn>(detail::ebo_get<bti<n>>(static_cast<Other&&>(other)))...
{ }
template <typename ...Yn>
explicit constexpr basic_tuple_impl(Yn&& ...yn)
- : detail::elt<n, Xn>(static_cast<Yn&&>(yn))...
+ : detail::ebo<bti<n>, Xn>(static_cast<Yn&&>(yn))...
{ }
};
}
@@ -177,7 +108,9 @@ BOOST_HANA_NAMESPACE_BEGIN
static constexpr decltype(auto)
apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F&& f) {
return static_cast<F&&>(f)(
- get_impl<i>(static_cast<detail::elt<i, Xn> const&>(xs))...
+ detail::ebo_get<detail::bti<i>>(
+ static_cast<detail::ebo<detail::bti<i>, Xn> const&>(xs)
+ )...
);
}
@@ -185,7 +118,9 @@ BOOST_HANA_NAMESPACE_BEGIN
static constexpr decltype(auto)
apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F&& f) {
return static_cast<F&&>(f)(
- get_impl<i>(static_cast<detail::elt<i, Xn>&>(xs))...
+ detail::ebo_get<detail::bti<i>>(
+ static_cast<detail::ebo<detail::bti<i>, Xn>&>(xs)
+ )...
);
}
@@ -193,7 +128,9 @@ BOOST_HANA_NAMESPACE_BEGIN
static constexpr decltype(auto)
apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F&& f) {
return static_cast<F&&>(f)(
- get_impl<i>(static_cast<detail::elt<i, Xn>&&>(xs))...
+ detail::ebo_get<detail::bti<i>>(
+ static_cast<detail::ebo<detail::bti<i>, Xn>&&>(xs)
+ )...
);
}
};
@@ -207,7 +144,9 @@ BOOST_HANA_NAMESPACE_BEGIN
static constexpr auto
apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F const& f) {
return hana::make_basic_tuple(
- f(get_impl<i>(static_cast<detail::elt<i, Xn> const&>(xs)))...
+ f(detail::ebo_get<detail::bti<i>>(
+ static_cast<detail::ebo<detail::bti<i>, Xn> const&>(xs)
+ ))...
);
}
@@ -215,7 +154,9 @@ BOOST_HANA_NAMESPACE_BEGIN
static constexpr auto
apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F const& f) {
return hana::make_basic_tuple(
- f(get_impl<i>(static_cast<detail::elt<i, Xn>&>(xs)))...
+ f(detail::ebo_get<detail::bti<i>>(
+ static_cast<detail::ebo<detail::bti<i>, Xn>&>(xs)
+ ))...
);
}
@@ -223,7 +164,9 @@ BOOST_HANA_NAMESPACE_BEGIN
static constexpr auto
apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F const& f) {
return hana::make_basic_tuple(
- f(get_impl<i>(static_cast<detail::elt<i, Xn>&&>(xs)))...
+ f(detail::ebo_get<detail::bti<i>>(
+ static_cast<detail::ebo<detail::bti<i>, Xn>&&>(xs)
+ ))...
);
}
};
@@ -236,7 +179,7 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename Xs, typename N>
static constexpr decltype(auto) apply(Xs&& xs, N const&) {
constexpr std::size_t index = N::value;
- return hana::get_impl<index>(static_cast<Xs&&>(xs));
+ return detail::ebo_get<detail::bti<index>>(static_cast<Xs&&>(xs));
}
};
@@ -244,7 +187,9 @@ BOOST_HANA_NAMESPACE_BEGIN
struct drop_front_impl<basic_tuple_tag> {
template <std::size_t N, typename Xs, std::size_t ...i>
static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
- return hana::make_basic_tuple(hana::get_impl<i+N>(static_cast<Xs&&>(xs))...);
+ return hana::make_basic_tuple(
+ detail::ebo_get<detail::bti<i+N>>(static_cast<Xs&&>(xs))...
+ );
}
template <typename Xs, typename N>
@@ -264,6 +209,22 @@ BOOST_HANA_NAMESPACE_BEGIN
{ return {}; }
};
+ // compile-time optimizations (to reduce the # of function instantiations)
+ template <std::size_t n, typename ...Xs>
+ constexpr decltype(auto) at_c(basic_tuple<Xs...> const& xs) {
+ return detail::ebo_get<detail::bti<n>>(xs);
+ }
+
+ template <std::size_t n, typename ...Xs>
+ constexpr decltype(auto) at_c(basic_tuple<Xs...>& xs) {
+ return detail::ebo_get<detail::bti<n>>(xs);
+ }
+
+ template <std::size_t n, typename ...Xs>
+ constexpr decltype(auto) at_c(basic_tuple<Xs...>&& xs) {
+ return detail::ebo_get<detail::bti<n>>(static_cast<basic_tuple<Xs...>&&>(xs));
+ }
+
//////////////////////////////////////////////////////////////////////////
// Sequence
//////////////////////////////////////////////////////////////////////////
diff --git a/boost/hana/bool.hpp b/boost/hana/bool.hpp
index 7ba1bfcb6c..0f62560a5a 100644
--- a/boost/hana/bool.hpp
+++ b/boost/hana/bool.hpp
@@ -2,7 +2,7 @@
@file
Defines the `Logical` and `Comparable` models of `boost::hana::integral_constant`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/cartesian_product.hpp b/boost/hana/cartesian_product.hpp
index 2303aa1332..eaf8bb4d9a 100644
--- a/boost/hana/cartesian_product.hpp
+++ b/boost/hana/cartesian_product.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::cartesian_product`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/chain.hpp b/boost/hana/chain.hpp
index da9de375f2..ab889d186a 100644
--- a/boost/hana/chain.hpp
+++ b/boost/hana/chain.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::chain`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/comparing.hpp b/boost/hana/comparing.hpp
index beae9cbda0..4aaa546d4c 100644
--- a/boost/hana/comparing.hpp
+++ b/boost/hana/comparing.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::comparing`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concat.hpp b/boost/hana/concat.hpp
index 8f079992b5..27f2ad0bf2 100644
--- a/boost/hana/concat.hpp
+++ b/boost/hana/concat.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::concat`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept.hpp b/boost/hana/concept.hpp
index 0ae73d8b7b..6046b0a4ef 100644
--- a/boost/hana/concept.hpp
+++ b/boost/hana/concept.hpp
@@ -2,7 +2,7 @@
@file
Master header for the `boost/hana/concept/` subdirectory.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/applicative.hpp b/boost/hana/concept/applicative.hpp
index 9227b1d1d1..84b92927eb 100644
--- a/boost/hana/concept/applicative.hpp
+++ b/boost/hana/concept/applicative.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Applicative`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/comonad.hpp b/boost/hana/concept/comonad.hpp
index 5d3a49a4e8..6cf950590f 100644
--- a/boost/hana/concept/comonad.hpp
+++ b/boost/hana/concept/comonad.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Comonad`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/comparable.hpp b/boost/hana/concept/comparable.hpp
index 96c28be7e9..bcecfcd0ab 100644
--- a/boost/hana/concept/comparable.hpp
+++ b/boost/hana/concept/comparable.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Comparable`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/constant.hpp b/boost/hana/concept/constant.hpp
index 08e5db248f..5e549ddf76 100644
--- a/boost/hana/concept/constant.hpp
+++ b/boost/hana/concept/constant.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Constant`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/euclidean_ring.hpp b/boost/hana/concept/euclidean_ring.hpp
index c58cb9fc45..e0de0477b0 100644
--- a/boost/hana/concept/euclidean_ring.hpp
+++ b/boost/hana/concept/euclidean_ring.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::EuclideanRing`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/foldable.hpp b/boost/hana/concept/foldable.hpp
index 5efd153c2f..6d88b58285 100644
--- a/boost/hana/concept/foldable.hpp
+++ b/boost/hana/concept/foldable.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Foldable`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/functor.hpp b/boost/hana/concept/functor.hpp
index 1a84126f6f..4fe7428b32 100644
--- a/boost/hana/concept/functor.hpp
+++ b/boost/hana/concept/functor.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Functor`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/group.hpp b/boost/hana/concept/group.hpp
index 5c8c34edf5..2b16728b4f 100644
--- a/boost/hana/concept/group.hpp
+++ b/boost/hana/concept/group.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Group`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/integral_constant.hpp b/boost/hana/concept/integral_constant.hpp
index 599adf5bef..cfb761da9b 100644
--- a/boost/hana/concept/integral_constant.hpp
+++ b/boost/hana/concept/integral_constant.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::IntegralConstant`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/iterable.hpp b/boost/hana/concept/iterable.hpp
index 9cf68b7b43..2949f70b2b 100644
--- a/boost/hana/concept/iterable.hpp
+++ b/boost/hana/concept/iterable.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Iterable`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/logical.hpp b/boost/hana/concept/logical.hpp
index ecfd0a4ebe..69e3079065 100644
--- a/boost/hana/concept/logical.hpp
+++ b/boost/hana/concept/logical.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Logical`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/metafunction.hpp b/boost/hana/concept/metafunction.hpp
index 61713e2b2e..70a9b0092a 100644
--- a/boost/hana/concept/metafunction.hpp
+++ b/boost/hana/concept/metafunction.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Metafunction`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/monad.hpp b/boost/hana/concept/monad.hpp
index e586192b4a..85fa06f9c3 100644
--- a/boost/hana/concept/monad.hpp
+++ b/boost/hana/concept/monad.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Monad`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/monad_plus.hpp b/boost/hana/concept/monad_plus.hpp
index c561e5af82..e9f2f1bf09 100644
--- a/boost/hana/concept/monad_plus.hpp
+++ b/boost/hana/concept/monad_plus.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::MonadPlus`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/monoid.hpp b/boost/hana/concept/monoid.hpp
index 024ce4fe28..adda475a26 100644
--- a/boost/hana/concept/monoid.hpp
+++ b/boost/hana/concept/monoid.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Monoid`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/orderable.hpp b/boost/hana/concept/orderable.hpp
index 1e9303d204..dfa82655fc 100644
--- a/boost/hana/concept/orderable.hpp
+++ b/boost/hana/concept/orderable.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Orderable`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/product.hpp b/boost/hana/concept/product.hpp
index 3ad8a70f2b..b1292ba156 100644
--- a/boost/hana/concept/product.hpp
+++ b/boost/hana/concept/product.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Product`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/ring.hpp b/boost/hana/concept/ring.hpp
index 700b3f6bb8..a9598e8fb3 100644
--- a/boost/hana/concept/ring.hpp
+++ b/boost/hana/concept/ring.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Ring`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/searchable.hpp b/boost/hana/concept/searchable.hpp
index 0ee98907bf..65b161de73 100644
--- a/boost/hana/concept/searchable.hpp
+++ b/boost/hana/concept/searchable.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Searchable`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/sequence.hpp b/boost/hana/concept/sequence.hpp
index fb5b83a2de..83e4b42d3d 100644
--- a/boost/hana/concept/sequence.hpp
+++ b/boost/hana/concept/sequence.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Sequence`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/concept/struct.hpp b/boost/hana/concept/struct.hpp
index 62183f44f6..49ac53b59c 100644
--- a/boost/hana/concept/struct.hpp
+++ b/boost/hana/concept/struct.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::Struct`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/config.hpp b/boost/hana/config.hpp
index de7d1dc794..6cf6ace710 100644
--- a/boost/hana/config.hpp
+++ b/boost/hana/config.hpp
@@ -2,7 +2,7 @@
@file
Defines configuration macros used throughout the library.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/contains.hpp b/boost/hana/contains.hpp
index 8b8599d8f3..5e18a388dc 100644
--- a/boost/hana/contains.hpp
+++ b/boost/hana/contains.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::contains` and `boost::hana::in`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/core.hpp b/boost/hana/core.hpp
index d028ff15ed..fa280f3336 100644
--- a/boost/hana/core.hpp
+++ b/boost/hana/core.hpp
@@ -2,7 +2,7 @@
@file
Defines the @ref group-core module.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/core/common.hpp b/boost/hana/core/common.hpp
index 471110ac68..c32de77feb 100644
--- a/boost/hana/core/common.hpp
+++ b/boost/hana/core/common.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::common` and `boost::hana::common_t`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/core/default.hpp b/boost/hana/core/default.hpp
index a03ffbb79a..45c70503c1 100644
--- a/boost/hana/core/default.hpp
+++ b/boost/hana/core/default.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::default_` and `boost::hana::is_default`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/core/dispatch.hpp b/boost/hana/core/dispatch.hpp
index 455766ad41..27a2fb493b 100644
--- a/boost/hana/core/dispatch.hpp
+++ b/boost/hana/core/dispatch.hpp
@@ -2,7 +2,7 @@
@file
Includes all the headers needed to setup tag-dispatching.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/core/is_a.hpp b/boost/hana/core/is_a.hpp
index 91cf45121a..019476ff0a 100644
--- a/boost/hana/core/is_a.hpp
+++ b/boost/hana/core/is_a.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::is_a` and `boost::hana::is_an`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/core/make.hpp b/boost/hana/core/make.hpp
index a4856a2ad5..53608df3f5 100644
--- a/boost/hana/core/make.hpp
+++ b/boost/hana/core/make.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::make`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/core/tag_of.hpp b/boost/hana/core/tag_of.hpp
index 5e469a3f90..87406521cd 100644
--- a/boost/hana/core/tag_of.hpp
+++ b/boost/hana/core/tag_of.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::tag_of` and `boost::hana::tag_of_t`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/core/to.hpp b/boost/hana/core/to.hpp
index 502c438f5c..6a6a115b3a 100644
--- a/boost/hana/core/to.hpp
+++ b/boost/hana/core/to.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::to` and related utilities.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/core/when.hpp b/boost/hana/core/when.hpp
index 06cb823a7c..0e5ee8e4e0 100644
--- a/boost/hana/core/when.hpp
+++ b/boost/hana/core/when.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::when` and `boost::hana::when_valid`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/count.hpp b/boost/hana/count.hpp
index cbdd218a46..b912c342db 100644
--- a/boost/hana/count.hpp
+++ b/boost/hana/count.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::count`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/count_if.hpp b/boost/hana/count_if.hpp
index fca164b687..e9ea4bc9c8 100644
--- a/boost/hana/count_if.hpp
+++ b/boost/hana/count_if.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::count_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/cycle.hpp b/boost/hana/cycle.hpp
index b3a2dcd849..c7b7a9ee32 100644
--- a/boost/hana/cycle.hpp
+++ b/boost/hana/cycle.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::cycle`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/define_struct.hpp b/boost/hana/define_struct.hpp
index 9ba80596a1..04ea728603 100644
--- a/boost/hana/define_struct.hpp
+++ b/boost/hana/define_struct.hpp
@@ -2,7 +2,7 @@
@file
Defines the `BOOST_HANA_DEFINE_STRUCT` macro.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/algorithm.hpp b/boost/hana/detail/algorithm.hpp
index cf4ead5751..1929847e7a 100644
--- a/boost/hana/detail/algorithm.hpp
+++ b/boost/hana/detail/algorithm.hpp
@@ -2,7 +2,7 @@
@file
Defines several `constexpr` algorithms.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/any_of.hpp b/boost/hana/detail/any_of.hpp
index 89c0d6a544..de6b1c6ad2 100644
--- a/boost/hana/detail/any_of.hpp
+++ b/boost/hana/detail/any_of.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::any_of`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/array.hpp b/boost/hana/detail/array.hpp
index eaf031da51..8b2c276f5e 100644
--- a/boost/hana/detail/array.hpp
+++ b/boost/hana/detail/array.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::array`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/canonical_constant.hpp b/boost/hana/detail/canonical_constant.hpp
index 0435ca0b42..07d636fa17 100644
--- a/boost/hana/detail/canonical_constant.hpp
+++ b/boost/hana/detail/canonical_constant.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::CanonicalConstant`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/concepts.hpp b/boost/hana/detail/concepts.hpp
index 6feed772c0..d7b48bc5ec 100644
--- a/boost/hana/detail/concepts.hpp
+++ b/boost/hana/detail/concepts.hpp
@@ -2,7 +2,7 @@
@file
Defines concepts from the Standard library.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/create.hpp b/boost/hana/detail/create.hpp
index e98537eb44..354e5590ca 100644
--- a/boost/hana/detail/create.hpp
+++ b/boost/hana/detail/create.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::create`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/decay.hpp b/boost/hana/detail/decay.hpp
index 014981c677..7d8affa0b2 100644
--- a/boost/hana/detail/decay.hpp
+++ b/boost/hana/detail/decay.hpp
@@ -3,7 +3,7 @@
Defines a replacement for `std::decay`, which is sometimes too slow at
compile-time.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/dependent_on.hpp b/boost/hana/detail/dependent_on.hpp
deleted file mode 100644
index 97141664b0..0000000000
--- a/boost/hana/detail/dependent_on.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*!
-@file
-Defines `boost::hana::detail::dependent_on`.
-
-@copyright Louis Dionne 2013-2016
-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_DETAIL_DEPENDENT_ON_HPP
-#define BOOST_HANA_DETAIL_DEPENDENT_ON_HPP
-
-#include <boost/hana/config.hpp>
-
-
-BOOST_HANA_NAMESPACE_BEGIN namespace detail {
- template <bool dummy, typename T>
- struct dependent_on { using type = T; };
-
- template <bool dummy, typename T>
- using dependent_on_t = typename dependent_on<dummy, T>::type;
-} BOOST_HANA_NAMESPACE_END
-
-#endif // !BOOST_HANA_DETAIL_DEPENDENT_ON_HPP
diff --git a/boost/hana/detail/dispatch_if.hpp b/boost/hana/detail/dispatch_if.hpp
index 88073fa7a2..6e95f58878 100644
--- a/boost/hana/detail/dispatch_if.hpp
+++ b/boost/hana/detail/dispatch_if.hpp
@@ -2,7 +2,7 @@
@file
Defines `BOOST_HANA_DISPATCH_IF`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/ebo.hpp b/boost/hana/detail/ebo.hpp
new file mode 100644
index 0000000000..01ca009ce2
--- /dev/null
+++ b/boost/hana/detail/ebo.hpp
@@ -0,0 +1,115 @@
+/*!
+@file
+Defines `boost::hana::detail::ebo`.
+
+@copyright Louis Dionne 2013-2016
+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_DETAIL_EBO_HPP
+#define BOOST_HANA_DETAIL_EBO_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/intrinsics.hpp>
+
+
+namespace _hana {
+ //////////////////////////////////////////////////////////////////////////
+ // ebo<K, V>
+ //
+ // Building block to implement the Empty Base Optimization (EBO). We
+ // use a short name and define it in a short namespace to reduce
+ // symbol lengths, since this type is used as a building block for
+ // other widely used types such as `hana::pair`.
+ //
+ // When available, we use compiler intrinsics to reduce the number
+ // of instantiations.
+ //
+ // `ebo` provides a limited set of constructors to reduce instantiations.
+ // Also, the constructors are open-ended and they do not check for the
+ // validity of their arguments, again to reduce compile-time costs.
+ // Users of `ebo` should make sure that they only try to construct an
+ // `ebo` from a compatible value.
+ //
+ // EBOs can be indexed using an arbitrary type. The recommended usage is
+ // to define an integrap constant wrapper for the specific container using
+ // EBO, and then index using that wrapper:
+ //
+ // template <int> struct idx; // wrapper for tuple
+ // template <typename ...T>
+ // struct tuple : ebo<idx<0>, T0>, ebo<idx<1>, T1>, ... { };
+ //
+ // The reason for defining one wrapper per container is to avoid any issues
+ // that can arise when using `ebo_get`, which casts to the base class. If
+ // `tuple` and `pair` are inheritting from `ebo`s with the same indexing
+ // scheme, trying to use `ebo_get` on a tuple of pairs will trigger an
+ // ambiguous base class conversion, since both tuple and pair inherit
+ // from `ebo`s with the same keys.
+ //////////////////////////////////////////////////////////////////////////
+ template <typename K, typename V, bool =
+ BOOST_HANA_TT_IS_EMPTY(V) && !BOOST_HANA_TT_IS_FINAL(V)
+ >
+ struct ebo;
+
+ // Specialize storage for empty types
+ template <typename K, typename V>
+ struct ebo<K, V, true> : V {
+ constexpr ebo() { }
+
+ template <typename T>
+ explicit constexpr ebo(T&& t)
+ : V(static_cast<T&&>(t))
+ { }
+ };
+
+ // Specialize storage for non-empty types
+ template <typename K, typename V>
+ struct ebo<K, V, false> {
+ constexpr ebo() : data_() { }
+
+ template <typename T>
+ explicit constexpr ebo(T&& t)
+ : data_(static_cast<T&&>(t))
+ { }
+
+ V data_;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // ebo_get
+ //////////////////////////////////////////////////////////////////////////
+ template <typename K, typename V>
+ constexpr V const& ebo_get(ebo<K, V, true> const& x)
+ { return x; }
+
+ template <typename K, typename V>
+ constexpr V& ebo_get(ebo<K, V, true>& x)
+ { return x; }
+
+ template <typename K, typename V>
+ constexpr V&& ebo_get(ebo<K, V, true>&& x)
+ { return static_cast<V&&>(x); }
+
+
+ template <typename K, typename V>
+ constexpr V const& ebo_get(ebo<K, V, false> const& x)
+ { return x.data_; }
+
+ template <typename K, typename V>
+ constexpr V& ebo_get(ebo<K, V, false>& x)
+ { return x.data_; }
+
+ template <typename K, typename V>
+ constexpr V&& ebo_get(ebo<K, V, false>&& x)
+ { return static_cast<V&&>(x.data_); }
+} // end namespace _hana
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace detail {
+ using ::_hana::ebo;
+ using ::_hana::ebo_get;
+ }
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_EBO_HPP
diff --git a/boost/hana/detail/fast_and.hpp b/boost/hana/detail/fast_and.hpp
index a03ab05bcf..a43e3e9c45 100644
--- a/boost/hana/detail/fast_and.hpp
+++ b/boost/hana/detail/fast_and.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::fast_and`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/first_unsatisfied_index.hpp b/boost/hana/detail/first_unsatisfied_index.hpp
index d4a894e4bd..e42cc598e5 100644
--- a/boost/hana/detail/first_unsatisfied_index.hpp
+++ b/boost/hana/detail/first_unsatisfied_index.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::first_unsatisfied_index`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/has_common_embedding.hpp b/boost/hana/detail/has_common_embedding.hpp
index d1e8db5861..ffaf6908b8 100644
--- a/boost/hana/detail/has_common_embedding.hpp
+++ b/boost/hana/detail/has_common_embedding.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::has_[nontrivial_]common_embedding`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/has_duplicates.hpp b/boost/hana/detail/has_duplicates.hpp
index 191f1e744e..ff9f080482 100644
--- a/boost/hana/detail/has_duplicates.hpp
+++ b/boost/hana/detail/has_duplicates.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::has_duplicates`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/index_if.hpp b/boost/hana/detail/index_if.hpp
index 81f6ea5630..8224f74be8 100644
--- a/boost/hana/detail/index_if.hpp
+++ b/boost/hana/detail/index_if.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::index_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/integral_constant.hpp b/boost/hana/detail/integral_constant.hpp
index aded3ba331..6fa7735164 100644
--- a/boost/hana/detail/integral_constant.hpp
+++ b/boost/hana/detail/integral_constant.hpp
@@ -3,7 +3,7 @@
Defines the barebones `boost::hana::integral_constant` template, but no
operations on it.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/intrinsics.hpp b/boost/hana/detail/intrinsics.hpp
index 6483f212aa..b3d98654cd 100644
--- a/boost/hana/detail/intrinsics.hpp
+++ b/boost/hana/detail/intrinsics.hpp
@@ -2,7 +2,7 @@
@file
Defines macros for commonly used type traits.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/nested_by.hpp b/boost/hana/detail/nested_by.hpp
index 5eabf3528b..6bdfe70c43 100644
--- a/boost/hana/detail/nested_by.hpp
+++ b/boost/hana/detail/nested_by.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::nested_by`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/nested_by_fwd.hpp b/boost/hana/detail/nested_by_fwd.hpp
index 3ca9dc7058..4e82f64cd6 100644
--- a/boost/hana/detail/nested_by_fwd.hpp
+++ b/boost/hana/detail/nested_by_fwd.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::detail::nested_by`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/nested_than.hpp b/boost/hana/detail/nested_than.hpp
index fce96eecf0..d4a7c5ffc6 100644
--- a/boost/hana/detail/nested_than.hpp
+++ b/boost/hana/detail/nested_than.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::nested_than`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/nested_than_fwd.hpp b/boost/hana/detail/nested_than_fwd.hpp
index 5e60d10251..39231050f3 100644
--- a/boost/hana/detail/nested_than_fwd.hpp
+++ b/boost/hana/detail/nested_than_fwd.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::detail::nested_than`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/nested_to.hpp b/boost/hana/detail/nested_to.hpp
index eee664ca93..2f6154d367 100644
--- a/boost/hana/detail/nested_to.hpp
+++ b/boost/hana/detail/nested_to.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::nested_to`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/nested_to_fwd.hpp b/boost/hana/detail/nested_to_fwd.hpp
index f21e0b181d..ec3161136c 100644
--- a/boost/hana/detail/nested_to_fwd.hpp
+++ b/boost/hana/detail/nested_to_fwd.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::detail::nested_to`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/operators/adl.hpp b/boost/hana/detail/operators/adl.hpp
index 22f804bad4..59a81600b6 100644
--- a/boost/hana/detail/operators/adl.hpp
+++ b/boost/hana/detail/operators/adl.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::operators::adl`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/operators/arithmetic.hpp b/boost/hana/detail/operators/arithmetic.hpp
index d0459115b8..58f432db78 100644
--- a/boost/hana/detail/operators/arithmetic.hpp
+++ b/boost/hana/detail/operators/arithmetic.hpp
@@ -2,7 +2,7 @@
@file
Defines arithmetic operators.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/operators/comparable.hpp b/boost/hana/detail/operators/comparable.hpp
index 579245f0f2..0c110fe3a3 100644
--- a/boost/hana/detail/operators/comparable.hpp
+++ b/boost/hana/detail/operators/comparable.hpp
@@ -2,7 +2,7 @@
@file
Defines operators for Comparables.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/operators/iterable.hpp b/boost/hana/detail/operators/iterable.hpp
index 95dadeedfe..6dcb6bc25e 100644
--- a/boost/hana/detail/operators/iterable.hpp
+++ b/boost/hana/detail/operators/iterable.hpp
@@ -2,7 +2,7 @@
@file
Defines operators for Iterables.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/operators/logical.hpp b/boost/hana/detail/operators/logical.hpp
index 28623df322..4645ca2bb4 100644
--- a/boost/hana/detail/operators/logical.hpp
+++ b/boost/hana/detail/operators/logical.hpp
@@ -2,7 +2,7 @@
@file
Defines logical operators.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/operators/monad.hpp b/boost/hana/detail/operators/monad.hpp
index 4cdf76b178..ccc421c56a 100644
--- a/boost/hana/detail/operators/monad.hpp
+++ b/boost/hana/detail/operators/monad.hpp
@@ -2,7 +2,7 @@
@file
Defines operators for Monads.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/operators/orderable.hpp b/boost/hana/detail/operators/orderable.hpp
index f60f14bbde..cf46829a04 100644
--- a/boost/hana/detail/operators/orderable.hpp
+++ b/boost/hana/detail/operators/orderable.hpp
@@ -2,7 +2,7 @@
@file
Defines operators for Orderables.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/operators/searchable.hpp b/boost/hana/detail/operators/searchable.hpp
index 7b4cc231e7..69d67465da 100644
--- a/boost/hana/detail/operators/searchable.hpp
+++ b/boost/hana/detail/operators/searchable.hpp
@@ -2,7 +2,7 @@
@file
Defines operators for Searchables.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/preprocessor.hpp b/boost/hana/detail/preprocessor.hpp
index a0432e8b44..cdeba70444 100644
--- a/boost/hana/detail/preprocessor.hpp
+++ b/boost/hana/detail/preprocessor.hpp
@@ -2,7 +2,7 @@
@file
Defines generally useful preprocessor macros.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/std_common_type.hpp b/boost/hana/detail/std_common_type.hpp
index 2eb0d6847e..b5fe6f318e 100644
--- a/boost/hana/detail/std_common_type.hpp
+++ b/boost/hana/detail/std_common_type.hpp
@@ -2,7 +2,7 @@
@file
Defines a SFINAE-friendly version of `std::common_type`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/struct_macros.erb.hpp b/boost/hana/detail/struct_macros.erb.hpp
index dfd94b1340..2cdc419593 100644
--- a/boost/hana/detail/struct_macros.erb.hpp
+++ b/boost/hana/detail/struct_macros.erb.hpp
@@ -23,7 +23,7 @@
Defines the `BOOST_HANA_DEFINE_STRUCT`, `BOOST_HANA_ADAPT_STRUCT`, and
`BOOST_HANA_ADAPT_ADT` macros.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/struct_macros.hpp b/boost/hana/detail/struct_macros.hpp
index daeeb8a57a..ff361c3570 100644
--- a/boost/hana/detail/struct_macros.hpp
+++ b/boost/hana/detail/struct_macros.hpp
@@ -7,7 +7,7 @@
Defines the `BOOST_HANA_DEFINE_STRUCT`, `BOOST_HANA_ADAPT_STRUCT`, and
`BOOST_HANA_ADAPT_ADT` macros.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/type_at.hpp b/boost/hana/detail/type_at.hpp
index 5875483d24..c7b8311f47 100644
--- a/boost/hana/detail/type_at.hpp
+++ b/boost/hana/detail/type_at.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::type_at`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/type_foldl1.hpp b/boost/hana/detail/type_foldl1.hpp
index 98f2947427..b65e3463fe 100644
--- a/boost/hana/detail/type_foldl1.hpp
+++ b/boost/hana/detail/type_foldl1.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::type_foldl1`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/type_foldr1.hpp b/boost/hana/detail/type_foldr1.hpp
index 3453d4467b..badf1b03d6 100644
--- a/boost/hana/detail/type_foldr1.hpp
+++ b/boost/hana/detail/type_foldr1.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::type_foldr1`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/unpack_flatten.hpp b/boost/hana/detail/unpack_flatten.hpp
index f72501a644..0c65e803bb 100644
--- a/boost/hana/detail/unpack_flatten.hpp
+++ b/boost/hana/detail/unpack_flatten.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::unpack_flatten`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/variadic/at.hpp b/boost/hana/detail/variadic/at.hpp
index 705d0e2ccc..9ef9e2944d 100644
--- a/boost/hana/detail/variadic/at.hpp
+++ b/boost/hana/detail/variadic/at.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::variadic::at`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/variadic/drop_into.hpp b/boost/hana/detail/variadic/drop_into.hpp
index 9e5a80f5dd..b31d1e98d5 100644
--- a/boost/hana/detail/variadic/drop_into.hpp
+++ b/boost/hana/detail/variadic/drop_into.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::variadic::drop_into`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/variadic/foldl1.hpp b/boost/hana/detail/variadic/foldl1.hpp
index ad2946b05f..320755f7c7 100644
--- a/boost/hana/detail/variadic/foldl1.hpp
+++ b/boost/hana/detail/variadic/foldl1.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::variadic::foldl1`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/variadic/foldr1.hpp b/boost/hana/detail/variadic/foldr1.hpp
index 88b5c95305..6221451d90 100644
--- a/boost/hana/detail/variadic/foldr1.hpp
+++ b/boost/hana/detail/variadic/foldr1.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::variadic::foldr1`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/variadic/reverse_apply.hpp b/boost/hana/detail/variadic/reverse_apply.hpp
index 08444a1035..b276fa4177 100644
--- a/boost/hana/detail/variadic/reverse_apply.hpp
+++ b/boost/hana/detail/variadic/reverse_apply.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::variadic::reverse_apply`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/variadic/reverse_apply/flat.hpp b/boost/hana/detail/variadic/reverse_apply/flat.hpp
index 6cd7bed53a..09bc818e6b 100644
--- a/boost/hana/detail/variadic/reverse_apply/flat.hpp
+++ b/boost/hana/detail/variadic/reverse_apply/flat.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::variadic::reverse_apply_flat`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/variadic/reverse_apply/unrolled.hpp b/boost/hana/detail/variadic/reverse_apply/unrolled.hpp
index 5cddf3c2c1..e6bf3d0c55 100644
--- a/boost/hana/detail/variadic/reverse_apply/unrolled.hpp
+++ b/boost/hana/detail/variadic/reverse_apply/unrolled.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::variadic::reverse_apply_unrolled`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/variadic/split_at.hpp b/boost/hana/detail/variadic/split_at.hpp
index 07e75088a6..c068c1bcb9 100644
--- a/boost/hana/detail/variadic/split_at.hpp
+++ b/boost/hana/detail/variadic/split_at.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::variadic::split_at`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/variadic/take.hpp b/boost/hana/detail/variadic/take.hpp
index 01da4b5b29..4d97a5b853 100644
--- a/boost/hana/detail/variadic/take.hpp
+++ b/boost/hana/detail/variadic/take.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::variadic::take`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/void_t.hpp b/boost/hana/detail/void_t.hpp
index f8152d378f..9eedd11441 100644
--- a/boost/hana/detail/void_t.hpp
+++ b/boost/hana/detail/void_t.hpp
@@ -2,7 +2,7 @@
@file
Defines an equivalent to the proposed `std::void_t`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/detail/wrong.hpp b/boost/hana/detail/wrong.hpp
index 99ca630dd1..ce5544fcdf 100644
--- a/boost/hana/detail/wrong.hpp
+++ b/boost/hana/detail/wrong.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::detail::wrong`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/difference.hpp b/boost/hana/difference.hpp
index a36223316b..158e727481 100644
--- a/boost/hana/difference.hpp
+++ b/boost/hana/difference.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::difference`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/div.hpp b/boost/hana/div.hpp
index ff41a36118..5b75ef10be 100644
--- a/boost/hana/div.hpp
+++ b/boost/hana/div.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::div`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/drop_back.hpp b/boost/hana/drop_back.hpp
index 6869a8b9f9..0e5837584a 100644
--- a/boost/hana/drop_back.hpp
+++ b/boost/hana/drop_back.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::drop_back`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/drop_front.hpp b/boost/hana/drop_front.hpp
index c06fbec593..2fa5ade108 100644
--- a/boost/hana/drop_front.hpp
+++ b/boost/hana/drop_front.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::drop_front`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/drop_front_exactly.hpp b/boost/hana/drop_front_exactly.hpp
index 61b43c4e2a..a6af69115d 100644
--- a/boost/hana/drop_front_exactly.hpp
+++ b/boost/hana/drop_front_exactly.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::drop_front_exactly`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/drop_while.hpp b/boost/hana/drop_while.hpp
index 53f58cf26a..b1f921b1d8 100644
--- a/boost/hana/drop_while.hpp
+++ b/boost/hana/drop_while.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::drop_while`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/duplicate.hpp b/boost/hana/duplicate.hpp
index 1df6fb7a85..783ae05fa0 100644
--- a/boost/hana/duplicate.hpp
+++ b/boost/hana/duplicate.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::duplicate`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/empty.hpp b/boost/hana/empty.hpp
index f20a5e5fff..8cb97a3ebc 100644
--- a/boost/hana/empty.hpp
+++ b/boost/hana/empty.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::empty`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/equal.hpp b/boost/hana/equal.hpp
index 8eb0912fca..1fa5e8bbe1 100644
--- a/boost/hana/equal.hpp
+++ b/boost/hana/equal.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::equal`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -29,7 +29,6 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/detail/concepts.hpp>
-#include <boost/hana/detail/dependent_on.hpp>
#include <boost/hana/detail/has_common_embedding.hpp>
#include <boost/hana/detail/nested_to.hpp> // required by fwd decl
#include <boost/hana/first.hpp>
@@ -56,7 +55,8 @@ BOOST_HANA_NAMESPACE_BEGIN
struct equal_impl<T, U, when<condition>> : default_ {
template <typename X, typename Y>
static constexpr auto apply(X const&, Y const&) {
- using T_ = detail::dependent_on_t<sizeof(X) == 1, T>;
+ // Delay the static_assert by ensuring T_ is dependent.
+ using T_ = typename hana::tag_of<X>::type;
static_assert(!hana::is_convertible<T_, U>::value &&
!hana::is_convertible<U, T_>::value,
"No default implementation of hana::equal is provided for related "
diff --git a/boost/hana/erase_key.hpp b/boost/hana/erase_key.hpp
index 20648f3c29..4a059c9598 100644
--- a/boost/hana/erase_key.hpp
+++ b/boost/hana/erase_key.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::erase_key`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/eval.hpp b/boost/hana/eval.hpp
index 1881c18277..1d8f4aa758 100644
--- a/boost/hana/eval.hpp
+++ b/boost/hana/eval.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::eval`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/eval_if.hpp b/boost/hana/eval_if.hpp
index e98d987447..7d0be870d3 100644
--- a/boost/hana/eval_if.hpp
+++ b/boost/hana/eval_if.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::eval_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -26,7 +26,7 @@ Distributed under the Boost Software License, Version 1.0.
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Cond, typename Then, typename Else>
- constexpr decltype(auto) eval_if_t::operator()(Cond&& cond, Then&& then, Else&& else_) const {
+ constexpr decltype(auto) eval_if_t::operator()(Cond&& cond, Then&& then_, Else&& else_) const {
using Bool = typename hana::tag_of<Cond>::type;
using EvalIf = BOOST_HANA_DISPATCH_IF(eval_if_impl<Bool>,
hana::Logical<Bool>::value
@@ -38,7 +38,7 @@ BOOST_HANA_NAMESPACE_BEGIN
#endif
return EvalIf::apply(static_cast<Cond&&>(cond),
- static_cast<Then&&>(then),
+ static_cast<Then&&>(then_),
static_cast<Else&&>(else_));
}
//! @endcond
@@ -83,7 +83,7 @@ BOOST_HANA_NAMESPACE_BEGIN
static constexpr decltype(auto) apply(Cond const&, Then&& t, Else&& e) {
constexpr auto cond = hana::value<Cond>();
constexpr bool truth_value = hana::if_(cond, true, false);
- return eval_if_helper(hana::bool_c<truth_value>,
+ return eval_if_helper(hana::bool_<truth_value>{},
static_cast<Then&&>(t),
static_cast<Else&&>(e));
}
diff --git a/boost/hana/experimental/printable.hpp b/boost/hana/experimental/printable.hpp
index 240e3a9291..e24a3426ea 100644
--- a/boost/hana/experimental/printable.hpp
+++ b/boost/hana/experimental/printable.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::experimental::print`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/experimental/type_name.hpp b/boost/hana/experimental/type_name.hpp
index 764b7eedd9..f3db176178 100644
--- a/boost/hana/experimental/type_name.hpp
+++ b/boost/hana/experimental/type_name.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::experimental::type_name`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/experimental/types.hpp b/boost/hana/experimental/types.hpp
index 75ae99e4f6..be1436a506 100644
--- a/boost/hana/experimental/types.hpp
+++ b/boost/hana/experimental/types.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::experimental::types`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/experimental/view.hpp b/boost/hana/experimental/view.hpp
index d037a9d271..e9a10b0820 100644
--- a/boost/hana/experimental/view.hpp
+++ b/boost/hana/experimental/view.hpp
@@ -2,7 +2,7 @@
@file
Defines experimental views.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/boost.hpp b/boost/hana/ext/boost.hpp
index 2d735c1469..aae8d5c27d 100644
--- a/boost/hana/ext/boost.hpp
+++ b/boost/hana/ext/boost.hpp
@@ -2,7 +2,7 @@
@file
Includes all the adaptors for external Boost libraries.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/boost/fusion.hpp b/boost/hana/ext/boost/fusion.hpp
index dd80e22b5a..7f775da9d9 100644
--- a/boost/hana/ext/boost/fusion.hpp
+++ b/boost/hana/ext/boost/fusion.hpp
@@ -2,7 +2,7 @@
@file
Includes all the adaptors for the Boost.Fusion library.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/boost/fusion/deque.hpp b/boost/hana/ext/boost/fusion/deque.hpp
index bdf8c14b84..698638157d 100644
--- a/boost/hana/ext/boost/fusion/deque.hpp
+++ b/boost/hana/ext/boost/fusion/deque.hpp
@@ -2,7 +2,7 @@
@file
Adapts `boost::fusion::deque` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/boost/fusion/detail/common.hpp b/boost/hana/ext/boost/fusion/detail/common.hpp
index c6ba922be5..298d74d93d 100644
--- a/boost/hana/ext/boost/fusion/detail/common.hpp
+++ b/boost/hana/ext/boost/fusion/detail/common.hpp
@@ -2,7 +2,7 @@
@file
Defines common methods for all Boost.Fusion sequences.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/boost/fusion/list.hpp b/boost/hana/ext/boost/fusion/list.hpp
index 0f30f7e7f8..0bdcb23dc5 100644
--- a/boost/hana/ext/boost/fusion/list.hpp
+++ b/boost/hana/ext/boost/fusion/list.hpp
@@ -2,7 +2,7 @@
@file
Adapts `boost::fusion::list` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/boost/fusion/tuple.hpp b/boost/hana/ext/boost/fusion/tuple.hpp
index d3e0757911..cf427e51d3 100644
--- a/boost/hana/ext/boost/fusion/tuple.hpp
+++ b/boost/hana/ext/boost/fusion/tuple.hpp
@@ -6,7 +6,7 @@ In the current version of Boost.Fusion, `boost::fusion::tuple` is basically
an alias to `boost::fusion::vector`, so both data types share the same
implementation in Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/boost/fusion/vector.hpp b/boost/hana/ext/boost/fusion/vector.hpp
index 8cf9bdbe50..9a2a3a8c5d 100644
--- a/boost/hana/ext/boost/fusion/vector.hpp
+++ b/boost/hana/ext/boost/fusion/vector.hpp
@@ -2,7 +2,7 @@
@file
Adapts `boost::fusion::vector` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/boost/mpl.hpp b/boost/hana/ext/boost/mpl.hpp
index 02bf0e1b0f..2188c83be2 100644
--- a/boost/hana/ext/boost/mpl.hpp
+++ b/boost/hana/ext/boost/mpl.hpp
@@ -2,7 +2,7 @@
@file
Includes all the adaptors for the Boost.MPL library.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/boost/mpl/integral_c.hpp b/boost/hana/ext/boost/mpl/integral_c.hpp
index ef2cad0239..68ddd18486 100644
--- a/boost/hana/ext/boost/mpl/integral_c.hpp
+++ b/boost/hana/ext/boost/mpl/integral_c.hpp
@@ -2,7 +2,7 @@
@file
Adapts Boost.MPL IntegralConstants for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/boost/mpl/list.hpp b/boost/hana/ext/boost/mpl/list.hpp
index 9e569a7d08..677b9a85bf 100644
--- a/boost/hana/ext/boost/mpl/list.hpp
+++ b/boost/hana/ext/boost/mpl/list.hpp
@@ -2,7 +2,7 @@
@file
Adapts `boost::mpl::list` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/boost/mpl/vector.hpp b/boost/hana/ext/boost/mpl/vector.hpp
index 59cac5dd2b..29e9972b5d 100644
--- a/boost/hana/ext/boost/mpl/vector.hpp
+++ b/boost/hana/ext/boost/mpl/vector.hpp
@@ -2,7 +2,7 @@
@file
Adapts `boost::mpl::vector` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/boost/tuple.hpp b/boost/hana/ext/boost/tuple.hpp
index dff9a4a952..581c973bda 100644
--- a/boost/hana/ext/boost/tuple.hpp
+++ b/boost/hana/ext/boost/tuple.hpp
@@ -2,7 +2,7 @@
@file
Adapts `boost::tuple` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/std.hpp b/boost/hana/ext/std.hpp
index 0d66408dc9..33b238d36e 100644
--- a/boost/hana/ext/std.hpp
+++ b/boost/hana/ext/std.hpp
@@ -2,7 +2,7 @@
@file
Includes all the adaptors for the standard library.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/std/array.hpp b/boost/hana/ext/std/array.hpp
index 15365f59cd..0cb513073c 100644
--- a/boost/hana/ext/std/array.hpp
+++ b/boost/hana/ext/std/array.hpp
@@ -2,7 +2,7 @@
@file
Adapts `std::array` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/std/integer_sequence.hpp b/boost/hana/ext/std/integer_sequence.hpp
index 27d01e3137..83536a3102 100644
--- a/boost/hana/ext/std/integer_sequence.hpp
+++ b/boost/hana/ext/std/integer_sequence.hpp
@@ -2,7 +2,7 @@
@file
Adapts `std::integer_sequence` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -105,8 +105,8 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename T, T ...v, typename N>
static constexpr auto apply(std::integer_sequence<T, v...> const&, N const&) {
constexpr std::size_t n = N::value;
- constexpr T values[] = {v...};
- return std::integral_constant<T, values[n]>{};
+ constexpr T values_[] = {v...};
+ return std::integral_constant<T, values_[n]>{};
}
};
diff --git a/boost/hana/ext/std/integral_constant.hpp b/boost/hana/ext/std/integral_constant.hpp
index 48db42400c..f949a66481 100644
--- a/boost/hana/ext/std/integral_constant.hpp
+++ b/boost/hana/ext/std/integral_constant.hpp
@@ -2,7 +2,7 @@
@file
Adapts `std::integral_constant` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/std/pair.hpp b/boost/hana/ext/std/pair.hpp
index fc60218e85..a2f429a642 100644
--- a/boost/hana/ext/std/pair.hpp
+++ b/boost/hana/ext/std/pair.hpp
@@ -2,7 +2,7 @@
@file
Adapts `std::pair` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/std/ratio.hpp b/boost/hana/ext/std/ratio.hpp
index a301abd1b6..bf25632f7d 100644
--- a/boost/hana/ext/std/ratio.hpp
+++ b/boost/hana/ext/std/ratio.hpp
@@ -2,7 +2,7 @@
@file
Adapts `std::ratio` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/std/tuple.hpp b/boost/hana/ext/std/tuple.hpp
index d53b9dd0f1..1edbf08334 100644
--- a/boost/hana/ext/std/tuple.hpp
+++ b/boost/hana/ext/std/tuple.hpp
@@ -2,7 +2,7 @@
@file
Adapts `std::tuple` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ext/std/vector.hpp b/boost/hana/ext/std/vector.hpp
index 62b808b2ea..d286d8f9a8 100644
--- a/boost/hana/ext/std/vector.hpp
+++ b/boost/hana/ext/std/vector.hpp
@@ -2,7 +2,7 @@
@file
Adapts `std::vector` for use with Hana.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-2017
@copyright Gonzalo Brito Gadeschi 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
diff --git a/boost/hana/extend.hpp b/boost/hana/extend.hpp
index c2568e41ec..466e74e777 100644
--- a/boost/hana/extend.hpp
+++ b/boost/hana/extend.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::extend`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/extract.hpp b/boost/hana/extract.hpp
index f72ddfce13..a9cd58624c 100644
--- a/boost/hana/extract.hpp
+++ b/boost/hana/extract.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::extract`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fill.hpp b/boost/hana/fill.hpp
index ce9c95392b..de82ac9b8e 100644
--- a/boost/hana/fill.hpp
+++ b/boost/hana/fill.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::fill`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/filter.hpp b/boost/hana/filter.hpp
index 0a5979dd3b..e8f7d51428 100644
--- a/boost/hana/filter.hpp
+++ b/boost/hana/filter.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::filter`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -93,7 +93,7 @@ BOOST_HANA_NAMESPACE_BEGIN
return indices;
}
- static constexpr auto indices = compute_indices();
+ static constexpr auto cached_indices = compute_indices();
};
template <typename Pred>
@@ -113,7 +113,7 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename Indices, typename Xs, std::size_t ...i>
static constexpr auto filter_helper(Xs&& xs, std::index_sequence<i...>) {
return hana::make<S>(
- hana::at_c<Indices::indices[i]>(static_cast<Xs&&>(xs))...
+ hana::at_c<Indices::cached_indices[i]>(static_cast<Xs&&>(xs))...
);
}
@@ -126,7 +126,7 @@ BOOST_HANA_NAMESPACE_BEGIN
return filter_impl::filter_helper<Indices>(
static_cast<Xs&&>(xs),
- std::make_index_sequence<Indices::indices.size()>{}
+ std::make_index_sequence<Indices::cached_indices.size()>{}
);
}
};
diff --git a/boost/hana/find.hpp b/boost/hana/find.hpp
index b2fe1ca8aa..4ebc48a2b5 100644
--- a/boost/hana/find.hpp
+++ b/boost/hana/find.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::find`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/find_if.hpp b/boost/hana/find_if.hpp
index 4de79e691e..3c4e07fcb0 100644
--- a/boost/hana/find_if.hpp
+++ b/boost/hana/find_if.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::find_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/first.hpp b/boost/hana/first.hpp
index 1e7ce828c3..f364b2242f 100644
--- a/boost/hana/first.hpp
+++ b/boost/hana/first.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::first`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/flatten.hpp b/boost/hana/flatten.hpp
index a481c3ae19..6c5ccc99c3 100644
--- a/boost/hana/flatten.hpp
+++ b/boost/hana/flatten.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::flatten`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fold.hpp b/boost/hana/fold.hpp
index 55adba06d1..a3665de22f 100644
--- a/boost/hana/fold.hpp
+++ b/boost/hana/fold.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::fold`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fold_left.hpp b/boost/hana/fold_left.hpp
index 23fee4035f..fc51b84d70 100644
--- a/boost/hana/fold_left.hpp
+++ b/boost/hana/fold_left.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::fold_left`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fold_right.hpp b/boost/hana/fold_right.hpp
index 60979a9201..73bdc6f88d 100644
--- a/boost/hana/fold_right.hpp
+++ b/boost/hana/fold_right.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::fold_right`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/for_each.hpp b/boost/hana/for_each.hpp
index 091b83c38c..defc1de4ad 100644
--- a/boost/hana/for_each.hpp
+++ b/boost/hana/for_each.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::for_each`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/front.hpp b/boost/hana/front.hpp
index e8b53de32d..96d7651a66 100644
--- a/boost/hana/front.hpp
+++ b/boost/hana/front.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::front`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional.hpp b/boost/hana/functional.hpp
index 152cf58bf0..8f649431b1 100644
--- a/boost/hana/functional.hpp
+++ b/boost/hana/functional.hpp
@@ -2,7 +2,7 @@
@file
Defines the @ref group-functional module.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/always.hpp b/boost/hana/functional/always.hpp
index 249233d3f2..df41b851e7 100644
--- a/boost/hana/functional/always.hpp
+++ b/boost/hana/functional/always.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::always`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/apply.hpp b/boost/hana/functional/apply.hpp
index 75a7f9483d..8a47a873e6 100644
--- a/boost/hana/functional/apply.hpp
+++ b/boost/hana/functional/apply.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::apply`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/arg.hpp b/boost/hana/functional/arg.hpp
index c9c68f0eae..5dd5658eff 100644
--- a/boost/hana/functional/arg.hpp
+++ b/boost/hana/functional/arg.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::arg`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/capture.hpp b/boost/hana/functional/capture.hpp
index 0b5a4677d8..65b4675833 100644
--- a/boost/hana/functional/capture.hpp
+++ b/boost/hana/functional/capture.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::capture`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -54,7 +54,7 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename F, typename Closure, std::size_t ...i>
constexpr auto apply_capture(F&& f, Closure&& closure, std::index_sequence<i...>) {
return hana::partial(static_cast<F&&>(f),
- hana::get_impl<i>(static_cast<Closure&&>(closure).storage_)...
+ hana::at_c<i>(static_cast<Closure&&>(closure).storage_)...
);
}
}
diff --git a/boost/hana/functional/compose.hpp b/boost/hana/functional/compose.hpp
index 3250cee4db..bbc53f6ff4 100644
--- a/boost/hana/functional/compose.hpp
+++ b/boost/hana/functional/compose.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::compose`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/curry.hpp b/boost/hana/functional/curry.hpp
index 94662757e5..74ec09459a 100644
--- a/boost/hana/functional/curry.hpp
+++ b/boost/hana/functional/curry.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::curry`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/demux.hpp b/boost/hana/functional/demux.hpp
index c1ed03634e..f76b68ed48 100644
--- a/boost/hana/functional/demux.hpp
+++ b/boost/hana/functional/demux.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::demux`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -211,22 +211,22 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) const& {
- return hana::get_impl<0>(storage_)(
- hana::get_impl<n+1>(storage_)(x...)...
+ return hana::at_c<0>(storage_)(
+ hana::at_c<n+1>(storage_)(x...)...
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) & {
- return hana::get_impl<0>(storage_)(
- hana::get_impl<n+1>(storage_)(x...)...
+ return hana::at_c<0>(storage_)(
+ hana::at_c<n+1>(storage_)(x...)...
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) && {
- return static_cast<F&&>(hana::get_impl<0>(storage_))(
- static_cast<G&&>(hana::get_impl<n+1>(storage_))(x...)...
+ return static_cast<F&&>(hana::at_c<0>(storage_))(
+ static_cast<G&&>(hana::at_c<n+1>(storage_))(x...)...
);
}
};
@@ -242,22 +242,22 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) const& {
- return hana::get_impl<0>(storage_)(
- hana::get_impl<1>(storage_)(static_cast<X&&>(x)...)
+ return hana::at_c<0>(storage_)(
+ hana::at_c<1>(storage_)(static_cast<X&&>(x)...)
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) & {
- return hana::get_impl<0>(storage_)(
- hana::get_impl<1>(storage_)(static_cast<X&&>(x)...)
+ return hana::at_c<0>(storage_)(
+ hana::at_c<1>(storage_)(static_cast<X&&>(x)...)
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) && {
- return static_cast<F&&>(hana::get_impl<0>(storage_))(
- static_cast<G&&>(hana::get_impl<1>(storage_))(static_cast<X&&>(x)...)
+ return static_cast<F&&>(hana::at_c<0>(storage_))(
+ static_cast<G&&>(hana::at_c<1>(storage_))(static_cast<X&&>(x)...)
);
}
};
diff --git a/boost/hana/functional/fix.hpp b/boost/hana/functional/fix.hpp
index 007ecba1a1..4c636ee10b 100644
--- a/boost/hana/functional/fix.hpp
+++ b/boost/hana/functional/fix.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::fix`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/flip.hpp b/boost/hana/functional/flip.hpp
index 3da81eddd7..d896f5e8d3 100644
--- a/boost/hana/functional/flip.hpp
+++ b/boost/hana/functional/flip.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::flip`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/id.hpp b/boost/hana/functional/id.hpp
index e6b4e32b79..04c9443b94 100644
--- a/boost/hana/functional/id.hpp
+++ b/boost/hana/functional/id.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::id`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/infix.hpp b/boost/hana/functional/infix.hpp
index 0706f3e62d..7b5d82cbe0 100644
--- a/boost/hana/functional/infix.hpp
+++ b/boost/hana/functional/infix.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::infix`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/iterate.hpp b/boost/hana/functional/iterate.hpp
index b2ec27f5ec..9a4ce3e9b2 100644
--- a/boost/hana/functional/iterate.hpp
+++ b/boost/hana/functional/iterate.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::iterate`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/lockstep.hpp b/boost/hana/functional/lockstep.hpp
index 11f8d6226f..2f60781883 100644
--- a/boost/hana/functional/lockstep.hpp
+++ b/boost/hana/functional/lockstep.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::lockstep`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -67,22 +67,22 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) const& {
- return hana::get_impl<0>(storage_)(
- hana::get_impl<n+1>(storage_)(static_cast<X&&>(x))...
+ return hana::at_c<0>(storage_)(
+ hana::at_c<n+1>(storage_)(static_cast<X&&>(x))...
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) & {
- return hana::get_impl<0>(storage_)(
- hana::get_impl<n+1>(storage_)(static_cast<X&&>(x))...
+ return hana::at_c<0>(storage_)(
+ hana::at_c<n+1>(storage_)(static_cast<X&&>(x))...
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) && {
- return static_cast<F&&>(hana::get_impl<0>(storage_))(
- static_cast<G&&>(hana::get_impl<n+1>(storage_))(static_cast<X&&>(x))...
+ return static_cast<F&&>(hana::at_c<0>(storage_))(
+ static_cast<G&&>(hana::at_c<n+1>(storage_))(static_cast<X&&>(x))...
);
}
};
diff --git a/boost/hana/functional/on.hpp b/boost/hana/functional/on.hpp
index ff40c0db5c..59561870a3 100644
--- a/boost/hana/functional/on.hpp
+++ b/boost/hana/functional/on.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::on`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/overload.hpp b/boost/hana/functional/overload.hpp
index b16c87c915..d8ce96a5ac 100644
--- a/boost/hana/functional/overload.hpp
+++ b/boost/hana/functional/overload.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::overload`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/overload_linearly.hpp b/boost/hana/functional/overload_linearly.hpp
index 3c91a9249f..e4129d1169 100644
--- a/boost/hana/functional/overload_linearly.hpp
+++ b/boost/hana/functional/overload_linearly.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::overload_linearly`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/functional/partial.hpp b/boost/hana/functional/partial.hpp
index 064d0058ac..cfe981dddf 100644
--- a/boost/hana/functional/partial.hpp
+++ b/boost/hana/functional/partial.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::partial`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -75,24 +75,24 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename ...Y>
constexpr decltype(auto) operator()(Y&& ...y) const& {
- return hana::get_impl<0>(storage_)(
- hana::get_impl<n+1>(storage_)...,
+ return hana::at_c<0>(storage_)(
+ hana::at_c<n+1>(storage_)...,
static_cast<Y&&>(y)...
);
}
template <typename ...Y>
constexpr decltype(auto) operator()(Y&& ...y) & {
- return hana::get_impl<0>(storage_)(
- hana::get_impl<n+1>(storage_)...,
+ return hana::at_c<0>(storage_)(
+ hana::at_c<n+1>(storage_)...,
static_cast<Y&&>(y)...
);
}
template <typename ...Y>
constexpr decltype(auto) operator()(Y&& ...y) && {
- return static_cast<F&&>(hana::get_impl<0>(storage_))(
- static_cast<X&&>(hana::get_impl<n+1>(storage_))...,
+ return static_cast<F&&>(hana::at_c<0>(storage_))(
+ static_cast<X&&>(hana::at_c<n+1>(storage_))...,
static_cast<Y&&>(y)...
);
}
diff --git a/boost/hana/functional/placeholder.hpp b/boost/hana/functional/placeholder.hpp
index 71a25389cd..59dea42bfb 100644
--- a/boost/hana/functional/placeholder.hpp
+++ b/boost/hana/functional/placeholder.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::_`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -92,7 +92,7 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename F, typename Xs, std::size_t ...i>
constexpr decltype(auto) invoke_impl(F&& f, Xs&& xs, std::index_sequence<i...>) {
- return static_cast<F&&>(f)(hana::get_impl<i>(static_cast<Xs&&>(xs).storage_)...);
+ return static_cast<F&&>(f)(hana::at_c<i>(static_cast<Xs&&>(xs).storage_)...);
}
template <typename ...X>
diff --git a/boost/hana/functional/reverse_partial.hpp b/boost/hana/functional/reverse_partial.hpp
index fe2a06f143..60fc59e400 100644
--- a/boost/hana/functional/reverse_partial.hpp
+++ b/boost/hana/functional/reverse_partial.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::reverse_partial`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -73,25 +73,25 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename ...Y>
constexpr decltype(auto) operator()(Y&& ...y) const& {
- return hana::get_impl<0>(storage_)(
+ return hana::at_c<0>(storage_)(
static_cast<Y&&>(y)...,
- hana::get_impl<n+1>(storage_)...
+ hana::at_c<n+1>(storage_)...
);
}
template <typename ...Y>
constexpr decltype(auto) operator()(Y&& ...y) & {
- return hana::get_impl<0>(storage_)(
+ return hana::at_c<0>(storage_)(
static_cast<Y&&>(y)...,
- hana::get_impl<n+1>(storage_)...
+ hana::at_c<n+1>(storage_)...
);
}
template <typename ...Y>
constexpr decltype(auto) operator()(Y&& ...y) && {
- return static_cast<F&&>(hana::get_impl<0>(storage_))(
+ return static_cast<F&&>(hana::at_c<0>(storage_))(
static_cast<Y&&>(y)...,
- static_cast<X&&>(hana::get_impl<n+1>(storage_))...
+ static_cast<X&&>(hana::at_c<n+1>(storage_))...
);
}
};
diff --git a/boost/hana/fuse.hpp b/boost/hana/fuse.hpp
index 38b93a151d..960aaee1bc 100644
--- a/boost/hana/fuse.hpp
+++ b/boost/hana/fuse.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::fuse`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/accessors.hpp b/boost/hana/fwd/accessors.hpp
index 8ad5f1b131..ca337d1965 100644
--- a/boost/hana/fwd/accessors.hpp
+++ b/boost/hana/fwd/accessors.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::accessors`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/adapt_adt.hpp b/boost/hana/fwd/adapt_adt.hpp
index 4b8614a612..a7658ca628 100644
--- a/boost/hana/fwd/adapt_adt.hpp
+++ b/boost/hana/fwd/adapt_adt.hpp
@@ -2,7 +2,7 @@
@file
Documents the `BOOST_HANA_ADAPT_ADT` macro.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/adapt_struct.hpp b/boost/hana/fwd/adapt_struct.hpp
index 691eecaf15..b03da6463b 100644
--- a/boost/hana/fwd/adapt_struct.hpp
+++ b/boost/hana/fwd/adapt_struct.hpp
@@ -2,7 +2,7 @@
@file
Documents the `BOOST_HANA_ADAPT_STRUCT` macro.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/adjust.hpp b/boost/hana/fwd/adjust.hpp
index c4a8783e9f..8fec6f0b3d 100644
--- a/boost/hana/fwd/adjust.hpp
+++ b/boost/hana/fwd/adjust.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::adjust`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/adjust_if.hpp b/boost/hana/fwd/adjust_if.hpp
index fac3cbf0e4..017ac03972 100644
--- a/boost/hana/fwd/adjust_if.hpp
+++ b/boost/hana/fwd/adjust_if.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::adjust_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/all.hpp b/boost/hana/fwd/all.hpp
index eb92a0c1e1..eca239ebef 100644
--- a/boost/hana/fwd/all.hpp
+++ b/boost/hana/fwd/all.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::all`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/all_of.hpp b/boost/hana/fwd/all_of.hpp
index 33fcbfc96d..3aabf29063 100644
--- a/boost/hana/fwd/all_of.hpp
+++ b/boost/hana/fwd/all_of.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::all_of`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/and.hpp b/boost/hana/fwd/and.hpp
index df767ebd1f..026cacabaf 100644
--- a/boost/hana/fwd/and.hpp
+++ b/boost/hana/fwd/and.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::and_`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/any.hpp b/boost/hana/fwd/any.hpp
index 2adf3beeee..6281236ad6 100644
--- a/boost/hana/fwd/any.hpp
+++ b/boost/hana/fwd/any.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::any`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/any_of.hpp b/boost/hana/fwd/any_of.hpp
index a8cf77596d..a9408bd1b5 100644
--- a/boost/hana/fwd/any_of.hpp
+++ b/boost/hana/fwd/any_of.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::any_of`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/ap.hpp b/boost/hana/fwd/ap.hpp
index 4d71abadd1..6f7b147090 100644
--- a/boost/hana/fwd/ap.hpp
+++ b/boost/hana/fwd/ap.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::ap`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/append.hpp b/boost/hana/fwd/append.hpp
index fd9efc3d53..94b2105c93 100644
--- a/boost/hana/fwd/append.hpp
+++ b/boost/hana/fwd/append.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::append`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/at.hpp b/boost/hana/fwd/at.hpp
index 9b1195d3d6..ea03114ed7 100644
--- a/boost/hana/fwd/at.hpp
+++ b/boost/hana/fwd/at.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::at` and `boost::hana::at_c`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/at_key.hpp b/boost/hana/fwd/at_key.hpp
index 08a29feff1..29134565a5 100644
--- a/boost/hana/fwd/at_key.hpp
+++ b/boost/hana/fwd/at_key.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::at_key`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/back.hpp b/boost/hana/fwd/back.hpp
index 197120aff7..8356cddeab 100644
--- a/boost/hana/fwd/back.hpp
+++ b/boost/hana/fwd/back.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::back`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/basic_tuple.hpp b/boost/hana/fwd/basic_tuple.hpp
index e2e78fbbcf..8444f0f50e 100644
--- a/boost/hana/fwd/basic_tuple.hpp
+++ b/boost/hana/fwd/basic_tuple.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::basic_tuple`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/bool.hpp b/boost/hana/fwd/bool.hpp
index 1bb712c99e..123c992c62 100644
--- a/boost/hana/fwd/bool.hpp
+++ b/boost/hana/fwd/bool.hpp
@@ -2,7 +2,7 @@
@file
Includes boost/hana/fwd/integral_constant.hpp.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/cartesian_product.hpp b/boost/hana/fwd/cartesian_product.hpp
index 4ea70626a6..a3a48f23f3 100644
--- a/boost/hana/fwd/cartesian_product.hpp
+++ b/boost/hana/fwd/cartesian_product.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::cartesian_product`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/chain.hpp b/boost/hana/fwd/chain.hpp
index e6ec0e141f..aa7f311057 100644
--- a/boost/hana/fwd/chain.hpp
+++ b/boost/hana/fwd/chain.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::chain`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/comparing.hpp b/boost/hana/fwd/comparing.hpp
index c508d48a21..376ab173c7 100644
--- a/boost/hana/fwd/comparing.hpp
+++ b/boost/hana/fwd/comparing.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::comparing`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concat.hpp b/boost/hana/fwd/concat.hpp
index ed87f71ec1..140c847909 100644
--- a/boost/hana/fwd/concat.hpp
+++ b/boost/hana/fwd/concat.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::concat`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/applicative.hpp b/boost/hana/fwd/concept/applicative.hpp
index 8f5db93042..2c8677940c 100644
--- a/boost/hana/fwd/concept/applicative.hpp
+++ b/boost/hana/fwd/concept/applicative.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Applicative`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/comonad.hpp b/boost/hana/fwd/concept/comonad.hpp
index 0c3627576b..b2693078b0 100644
--- a/boost/hana/fwd/concept/comonad.hpp
+++ b/boost/hana/fwd/concept/comonad.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Comonad`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/comparable.hpp b/boost/hana/fwd/concept/comparable.hpp
index 555dfdfa34..9624c87038 100644
--- a/boost/hana/fwd/concept/comparable.hpp
+++ b/boost/hana/fwd/concept/comparable.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Comparable`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/constant.hpp b/boost/hana/fwd/concept/constant.hpp
index a9c1467dbc..bab44a7cb2 100644
--- a/boost/hana/fwd/concept/constant.hpp
+++ b/boost/hana/fwd/concept/constant.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Constant`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -30,7 +30,7 @@ BOOST_HANA_NAMESPACE_BEGIN
//! Let `C(T)` and `D(U)` denote the tags of `Constant`s holding objects
//! of type `T` and `U`, respectively. Then, an object with tag `D(U)`
//! must be convertible to an object with tag `C(T)` whenever `U` is
- //! convertible to `T`, has determined by `is_convertible`. The
+ //! convertible to `T`, as determined by `is_convertible`. The
//! interpretation here is that a `Constant` is just a box holding
//! an object of some type, and it should be possible to swap between
//! boxes whenever the objects inside the boxes can be swapped.
@@ -59,7 +59,7 @@ BOOST_HANA_NAMESPACE_BEGIN
//! of the wrapped object is always a constant expression by requiring
//! the following to be well-formed:
//! @code
- //! constexpr auto x = hana::value<decltype(x)>();
+ //! constexpr auto x = hana::value<decltype(c)>();
//! @endcode
//!
//! This means that the `value` function must return an object that can
@@ -146,7 +146,7 @@ BOOST_HANA_NAMESPACE_BEGIN
//! conversion of underlying types is an embedding. This is to allow
//! Constants to inter-operate with `constexpr` objects easily:
//! @code
- //! plus(int_<1>, 1) == 2
+ //! plus(int_c<1>, 1) == 2
//! @endcode
//!
//! Strictly speaking, __this is sometimes a violation__ of what it means
@@ -160,25 +160,25 @@ BOOST_HANA_NAMESPACE_BEGIN
//! `constexpr` object of not. In other words, the `to` method has no way
//! to differentiate between
//! @code
- //! constexpr int i = hana::to<int>(int_<1>);
+ //! constexpr int i = hana::to<int>(int_c<1>);
//! @endcode
//! which is an embedding, and
//! @code
- //! int i = hana::to<int>(int_<1>);
+ //! int i = hana::to<int>(int_c<1>);
//! @endcode
//!
//! which isn't. To be on the safer side, we could mark the conversion
//! as not-an-embedding. However, if e.g. the conversion from
//! `integral_constant_tag<int>` to `int` was not marked as an embedding,
- //! we would have to write `plus(to<int>(int_<1>), 1)` instead of just
- //! `plus(int_<1>, 1)`, which is cumbersome. Hence, the conversion is
+ //! we would have to write `plus(to<int>(int_c<1>), 1)` instead of just
+ //! `plus(int_c<1>, 1)`, which is cumbersome. Hence, the conversion is
//! marked as an embedding, but this also means that code like
//! @code
//! int i = 1;
- //! plus(int_<1>, i);
+ //! plus(int_c<1>, i);
//! @endcode
//! will be considered valid, which implicitly loses the fact that
- //! `int_<1>` is a Constant, and hence does not follow the usual rules
+ //! `int_c<1>` is a Constant, and hence does not follow the usual rules
//! for cross-type operations in Hana.
//!
//!
diff --git a/boost/hana/fwd/concept/euclidean_ring.hpp b/boost/hana/fwd/concept/euclidean_ring.hpp
index b33d8b565c..8b8744c29d 100644
--- a/boost/hana/fwd/concept/euclidean_ring.hpp
+++ b/boost/hana/fwd/concept/euclidean_ring.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::EuclideanRing`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/foldable.hpp b/boost/hana/fwd/concept/foldable.hpp
index 6e460ad435..09de170455 100644
--- a/boost/hana/fwd/concept/foldable.hpp
+++ b/boost/hana/fwd/concept/foldable.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Foldable`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/functor.hpp b/boost/hana/fwd/concept/functor.hpp
index 6d2ea170f6..f46ad24c73 100644
--- a/boost/hana/fwd/concept/functor.hpp
+++ b/boost/hana/fwd/concept/functor.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Functor`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/group.hpp b/boost/hana/fwd/concept/group.hpp
index a7ec238d54..6afec94502 100644
--- a/boost/hana/fwd/concept/group.hpp
+++ b/boost/hana/fwd/concept/group.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Group`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/integral_constant.hpp b/boost/hana/fwd/concept/integral_constant.hpp
index ba82c52931..161062e2be 100644
--- a/boost/hana/fwd/concept/integral_constant.hpp
+++ b/boost/hana/fwd/concept/integral_constant.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::IntegralConstant`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/iterable.hpp b/boost/hana/fwd/concept/iterable.hpp
index f406b2186b..59c8520b62 100644
--- a/boost/hana/fwd/concept/iterable.hpp
+++ b/boost/hana/fwd/concept/iterable.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Iterable`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/logical.hpp b/boost/hana/fwd/concept/logical.hpp
index 7eecf9d857..f9cfde986c 100644
--- a/boost/hana/fwd/concept/logical.hpp
+++ b/boost/hana/fwd/concept/logical.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Logical`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/metafunction.hpp b/boost/hana/fwd/concept/metafunction.hpp
index 00efc049e3..72884911f3 100644
--- a/boost/hana/fwd/concept/metafunction.hpp
+++ b/boost/hana/fwd/concept/metafunction.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Metafunction`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/monad.hpp b/boost/hana/fwd/concept/monad.hpp
index 1dee78331d..b310868e44 100644
--- a/boost/hana/fwd/concept/monad.hpp
+++ b/boost/hana/fwd/concept/monad.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Monad`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/monad_plus.hpp b/boost/hana/fwd/concept/monad_plus.hpp
index a7ac03c4d3..dcdf65e210 100644
--- a/boost/hana/fwd/concept/monad_plus.hpp
+++ b/boost/hana/fwd/concept/monad_plus.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::MonadPlus`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/monoid.hpp b/boost/hana/fwd/concept/monoid.hpp
index 5486d3d1d8..381e29dff7 100644
--- a/boost/hana/fwd/concept/monoid.hpp
+++ b/boost/hana/fwd/concept/monoid.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Monoid`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/orderable.hpp b/boost/hana/fwd/concept/orderable.hpp
index ed381de94a..7c4cf233db 100644
--- a/boost/hana/fwd/concept/orderable.hpp
+++ b/boost/hana/fwd/concept/orderable.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Orderable`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/product.hpp b/boost/hana/fwd/concept/product.hpp
index f3b2feb705..0d029fdb11 100644
--- a/boost/hana/fwd/concept/product.hpp
+++ b/boost/hana/fwd/concept/product.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Product`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/ring.hpp b/boost/hana/fwd/concept/ring.hpp
index 91d150214e..45b301f272 100644
--- a/boost/hana/fwd/concept/ring.hpp
+++ b/boost/hana/fwd/concept/ring.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Ring`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/searchable.hpp b/boost/hana/fwd/concept/searchable.hpp
index 8a0491b2ec..2c1e22fc4a 100644
--- a/boost/hana/fwd/concept/searchable.hpp
+++ b/boost/hana/fwd/concept/searchable.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Searchable`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/sequence.hpp b/boost/hana/fwd/concept/sequence.hpp
index 7f9df2e39d..84cedd1263 100644
--- a/boost/hana/fwd/concept/sequence.hpp
+++ b/boost/hana/fwd/concept/sequence.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Sequence`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/concept/struct.hpp b/boost/hana/fwd/concept/struct.hpp
index f6829466bb..d9d0cffb58 100644
--- a/boost/hana/fwd/concept/struct.hpp
+++ b/boost/hana/fwd/concept/struct.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::Struct`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/contains.hpp b/boost/hana/fwd/contains.hpp
index f717f6738c..eb338281c1 100644
--- a/boost/hana/fwd/contains.hpp
+++ b/boost/hana/fwd/contains.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::contains` and `boost::hana::in`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/core.hpp b/boost/hana/fwd/core.hpp
index 10fad8ace9..a25a159582 100644
--- a/boost/hana/fwd/core.hpp
+++ b/boost/hana/fwd/core.hpp
@@ -2,7 +2,7 @@
@file
Forward declares the @ref group-core module.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/core/common.hpp b/boost/hana/fwd/core/common.hpp
index 29702f23d5..d2dcac59f7 100644
--- a/boost/hana/fwd/core/common.hpp
+++ b/boost/hana/fwd/core/common.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::common` and `boost::hana::common_t`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/core/default.hpp b/boost/hana/fwd/core/default.hpp
index 58e3f060f3..978c9a5f0c 100644
--- a/boost/hana/fwd/core/default.hpp
+++ b/boost/hana/fwd/core/default.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::default_` and `boost::hana::is_default`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/core/is_a.hpp b/boost/hana/fwd/core/is_a.hpp
index 5a90c6d55b..956549aa16 100644
--- a/boost/hana/fwd/core/is_a.hpp
+++ b/boost/hana/fwd/core/is_a.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::is_a` and `boost::hana::is_an`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/core/make.hpp b/boost/hana/fwd/core/make.hpp
index 56354b6813..0ed5d0f19e 100644
--- a/boost/hana/fwd/core/make.hpp
+++ b/boost/hana/fwd/core/make.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::make`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/core/tag_of.hpp b/boost/hana/fwd/core/tag_of.hpp
index a2e7cc5605..bcc4ef8e53 100644
--- a/boost/hana/fwd/core/tag_of.hpp
+++ b/boost/hana/fwd/core/tag_of.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::tag_of` and `boost::hana::tag_of_t`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/core/to.hpp b/boost/hana/fwd/core/to.hpp
index e41d36ee0a..108484c2ce 100644
--- a/boost/hana/fwd/core/to.hpp
+++ b/boost/hana/fwd/core/to.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::to` and related utilities.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/core/when.hpp b/boost/hana/fwd/core/when.hpp
index 857dc2581d..cc7659628d 100644
--- a/boost/hana/fwd/core/when.hpp
+++ b/boost/hana/fwd/core/when.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::when` and `boost::hana::when_valid`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/count.hpp b/boost/hana/fwd/count.hpp
index ffa4a1a65a..3bfdda53d6 100644
--- a/boost/hana/fwd/count.hpp
+++ b/boost/hana/fwd/count.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::count`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/count_if.hpp b/boost/hana/fwd/count_if.hpp
index 8d4b9283a9..8be0a42638 100644
--- a/boost/hana/fwd/count_if.hpp
+++ b/boost/hana/fwd/count_if.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::count_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/cycle.hpp b/boost/hana/fwd/cycle.hpp
index 4d23b8d821..268e7daf43 100644
--- a/boost/hana/fwd/cycle.hpp
+++ b/boost/hana/fwd/cycle.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::cycle`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/define_struct.hpp b/boost/hana/fwd/define_struct.hpp
index b4adb89f5c..831f6872a4 100644
--- a/boost/hana/fwd/define_struct.hpp
+++ b/boost/hana/fwd/define_struct.hpp
@@ -2,7 +2,7 @@
@file
Documents the `BOOST_HANA_DEFINE_STRUCT` macro.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/difference.hpp b/boost/hana/fwd/difference.hpp
index 44916198e5..3702f075e0 100644
--- a/boost/hana/fwd/difference.hpp
+++ b/boost/hana/fwd/difference.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::difference`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/div.hpp b/boost/hana/fwd/div.hpp
index 82684d7162..6f35b4abe3 100644
--- a/boost/hana/fwd/div.hpp
+++ b/boost/hana/fwd/div.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::div`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/drop_back.hpp b/boost/hana/fwd/drop_back.hpp
index 814382e855..440e925322 100644
--- a/boost/hana/fwd/drop_back.hpp
+++ b/boost/hana/fwd/drop_back.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::drop_back`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/drop_front.hpp b/boost/hana/fwd/drop_front.hpp
index b76c710ef7..298499180c 100644
--- a/boost/hana/fwd/drop_front.hpp
+++ b/boost/hana/fwd/drop_front.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::drop_front`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/drop_front_exactly.hpp b/boost/hana/fwd/drop_front_exactly.hpp
index 3cb11d76a7..17a55e6d66 100644
--- a/boost/hana/fwd/drop_front_exactly.hpp
+++ b/boost/hana/fwd/drop_front_exactly.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::drop_front_exactly`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/drop_while.hpp b/boost/hana/fwd/drop_while.hpp
index ef555f8609..2d5557e5a7 100644
--- a/boost/hana/fwd/drop_while.hpp
+++ b/boost/hana/fwd/drop_while.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::drop_while`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/duplicate.hpp b/boost/hana/fwd/duplicate.hpp
index b1a0af242b..bac61e0bd9 100644
--- a/boost/hana/fwd/duplicate.hpp
+++ b/boost/hana/fwd/duplicate.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::duplicate`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/empty.hpp b/boost/hana/fwd/empty.hpp
index 90a3696357..ed3cc38cc7 100644
--- a/boost/hana/fwd/empty.hpp
+++ b/boost/hana/fwd/empty.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::empty`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/equal.hpp b/boost/hana/fwd/equal.hpp
index e72614407d..e9f8c4bd6e 100644
--- a/boost/hana/fwd/equal.hpp
+++ b/boost/hana/fwd/equal.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::equal`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/erase_key.hpp b/boost/hana/fwd/erase_key.hpp
index 4612424802..49471d61cf 100644
--- a/boost/hana/fwd/erase_key.hpp
+++ b/boost/hana/fwd/erase_key.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::erase_key`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/eval.hpp b/boost/hana/fwd/eval.hpp
index d1d0b7f488..d068f992f5 100644
--- a/boost/hana/fwd/eval.hpp
+++ b/boost/hana/fwd/eval.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::eval`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/eval_if.hpp b/boost/hana/fwd/eval_if.hpp
index 865e561c99..2bc8736b12 100644
--- a/boost/hana/fwd/eval_if.hpp
+++ b/boost/hana/fwd/eval_if.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::eval_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/extend.hpp b/boost/hana/fwd/extend.hpp
index 6cbf1ffc2b..65b68d8011 100644
--- a/boost/hana/fwd/extend.hpp
+++ b/boost/hana/fwd/extend.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::extend`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/extract.hpp b/boost/hana/fwd/extract.hpp
index 8a9917bc66..1e71727143 100644
--- a/boost/hana/fwd/extract.hpp
+++ b/boost/hana/fwd/extract.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::extract`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/fill.hpp b/boost/hana/fwd/fill.hpp
index 38a4a35c96..6946c6ffd8 100644
--- a/boost/hana/fwd/fill.hpp
+++ b/boost/hana/fwd/fill.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::fill`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/filter.hpp b/boost/hana/fwd/filter.hpp
index b0db0b6006..f31b30df52 100644
--- a/boost/hana/fwd/filter.hpp
+++ b/boost/hana/fwd/filter.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::filter`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/find.hpp b/boost/hana/fwd/find.hpp
index 00c74d1a43..cc88d6f239 100644
--- a/boost/hana/fwd/find.hpp
+++ b/boost/hana/fwd/find.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::find`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/find_if.hpp b/boost/hana/fwd/find_if.hpp
index 7c8b8664f1..d6fca44600 100644
--- a/boost/hana/fwd/find_if.hpp
+++ b/boost/hana/fwd/find_if.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::find_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/first.hpp b/boost/hana/fwd/first.hpp
index 8cfef1472e..0a62a8344f 100644
--- a/boost/hana/fwd/first.hpp
+++ b/boost/hana/fwd/first.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::first`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/flatten.hpp b/boost/hana/fwd/flatten.hpp
index 42c83f8f22..f0e319a131 100644
--- a/boost/hana/fwd/flatten.hpp
+++ b/boost/hana/fwd/flatten.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::flatten`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/fold.hpp b/boost/hana/fwd/fold.hpp
index f34961d507..e060ab1e1e 100644
--- a/boost/hana/fwd/fold.hpp
+++ b/boost/hana/fwd/fold.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::fold`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/fold_left.hpp b/boost/hana/fwd/fold_left.hpp
index 039cb746d8..22dd22d32f 100644
--- a/boost/hana/fwd/fold_left.hpp
+++ b/boost/hana/fwd/fold_left.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::fold_left`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/fold_right.hpp b/boost/hana/fwd/fold_right.hpp
index 4b5bf8f1ba..a4305e9c72 100644
--- a/boost/hana/fwd/fold_right.hpp
+++ b/boost/hana/fwd/fold_right.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::fold_right`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/for_each.hpp b/boost/hana/fwd/for_each.hpp
index 35c0bd45ce..83daf25418 100644
--- a/boost/hana/fwd/for_each.hpp
+++ b/boost/hana/fwd/for_each.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::for_each`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/front.hpp b/boost/hana/fwd/front.hpp
index 805cbdd15d..3ac1602ea4 100644
--- a/boost/hana/fwd/front.hpp
+++ b/boost/hana/fwd/front.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::front`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/fuse.hpp b/boost/hana/fwd/fuse.hpp
index 6e38227c61..cecc97c73a 100644
--- a/boost/hana/fwd/fuse.hpp
+++ b/boost/hana/fwd/fuse.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::fuse`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/greater.hpp b/boost/hana/fwd/greater.hpp
index 091c1d36de..5fcaa4e32d 100644
--- a/boost/hana/fwd/greater.hpp
+++ b/boost/hana/fwd/greater.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::greater`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/greater_equal.hpp b/boost/hana/fwd/greater_equal.hpp
index d19c6734be..4b29bfcc96 100644
--- a/boost/hana/fwd/greater_equal.hpp
+++ b/boost/hana/fwd/greater_equal.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::greater_equal`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/group.hpp b/boost/hana/fwd/group.hpp
index 75fb68c832..1be1bee386 100644
--- a/boost/hana/fwd/group.hpp
+++ b/boost/hana/fwd/group.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::group`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/if.hpp b/boost/hana/fwd/if.hpp
index c221b355cf..59b61975f8 100644
--- a/boost/hana/fwd/if.hpp
+++ b/boost/hana/fwd/if.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::if_`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/insert.hpp b/boost/hana/fwd/insert.hpp
index 0ad88849c9..3ca9aa458d 100644
--- a/boost/hana/fwd/insert.hpp
+++ b/boost/hana/fwd/insert.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::insert`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/insert_range.hpp b/boost/hana/fwd/insert_range.hpp
index e424059c8c..88b6d98acd 100644
--- a/boost/hana/fwd/insert_range.hpp
+++ b/boost/hana/fwd/insert_range.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::insert_range`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/integral_constant.hpp b/boost/hana/fwd/integral_constant.hpp
index d05d6021f9..6ef1272d80 100644
--- a/boost/hana/fwd/integral_constant.hpp
+++ b/boost/hana/fwd/integral_constant.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::integral_constant`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/intersection.hpp b/boost/hana/fwd/intersection.hpp
index 787137e208..ec9b1daad2 100644
--- a/boost/hana/fwd/intersection.hpp
+++ b/boost/hana/fwd/intersection.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::intersection`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/intersperse.hpp b/boost/hana/fwd/intersperse.hpp
index fd29d3a321..35e8a725b5 100644
--- a/boost/hana/fwd/intersperse.hpp
+++ b/boost/hana/fwd/intersperse.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::intersperse`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/is_disjoint.hpp b/boost/hana/fwd/is_disjoint.hpp
index 97ed7471bb..8a3520b558 100644
--- a/boost/hana/fwd/is_disjoint.hpp
+++ b/boost/hana/fwd/is_disjoint.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::is_disjoint`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/is_empty.hpp b/boost/hana/fwd/is_empty.hpp
index ddc524672d..a33dc5af8c 100644
--- a/boost/hana/fwd/is_empty.hpp
+++ b/boost/hana/fwd/is_empty.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::is_empty`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/is_subset.hpp b/boost/hana/fwd/is_subset.hpp
index 158d28b751..aceb85aa86 100644
--- a/boost/hana/fwd/is_subset.hpp
+++ b/boost/hana/fwd/is_subset.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::is_subset`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/keys.hpp b/boost/hana/fwd/keys.hpp
index 285c34d9a1..24c93b749a 100644
--- a/boost/hana/fwd/keys.hpp
+++ b/boost/hana/fwd/keys.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::keys`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/lazy.hpp b/boost/hana/fwd/lazy.hpp
index 6ae6a830ef..7568e8e4a6 100644
--- a/boost/hana/fwd/lazy.hpp
+++ b/boost/hana/fwd/lazy.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::lazy`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/length.hpp b/boost/hana/fwd/length.hpp
index c995a80dd8..331b1d93d2 100644
--- a/boost/hana/fwd/length.hpp
+++ b/boost/hana/fwd/length.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::length`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/less.hpp b/boost/hana/fwd/less.hpp
index 1dd585db33..f1695b2b74 100644
--- a/boost/hana/fwd/less.hpp
+++ b/boost/hana/fwd/less.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::less`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/less_equal.hpp b/boost/hana/fwd/less_equal.hpp
index 9de3d6b779..e5c66e4bc3 100644
--- a/boost/hana/fwd/less_equal.hpp
+++ b/boost/hana/fwd/less_equal.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::less_equal`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/lexicographical_compare.hpp b/boost/hana/fwd/lexicographical_compare.hpp
index 0098b1cb2d..a95aac5212 100644
--- a/boost/hana/fwd/lexicographical_compare.hpp
+++ b/boost/hana/fwd/lexicographical_compare.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::lexicographical_compare`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/lift.hpp b/boost/hana/fwd/lift.hpp
index 2f30fd68d5..9491dab8a4 100644
--- a/boost/hana/fwd/lift.hpp
+++ b/boost/hana/fwd/lift.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::lift`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/map.hpp b/boost/hana/fwd/map.hpp
index 25ff7add35..bff0b012f0 100644
--- a/boost/hana/fwd/map.hpp
+++ b/boost/hana/fwd/map.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::map`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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,14 +17,17 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/fwd/insert.hpp>
#include <boost/hana/fwd/keys.hpp>
-#include <utility>
-
BOOST_HANA_NAMESPACE_BEGIN
//! Tag representing `hana::map`s.
//! @relates hana::map
struct map_tag { };
+ namespace detail {
+ template <typename ...Pairs>
+ struct make_map_type;
+ }
+
//! @ingroup group-datatypes
//! Basic associative container requiring unique, `Comparable` and
//! `Hashable` keys.
@@ -42,7 +45,7 @@ BOOST_HANA_NAMESPACE_BEGIN
//! - the fact that `hana::map<Pairs...>` is, or is not, a dependent type
//!
//! In particular, the last point is very important; `hana::map<Pairs...>`
- //! is only a shortcut for
+ //! is basically equivalent to
//! @code
//! decltype(hana::make_pair(std::declval<Pairs>()...))
//! @endcode
@@ -106,6 +109,14 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename ...P>
explicit constexpr map(P&& ...pairs);
+ //! Assign a map to another map __with the exact same type__. Only
+ //! exists when all the elements of the map are copy-assignable.
+ constexpr map& operator=(map const& other);
+
+ //! Move-assign a map to another map __with the exact same type__.
+ //! Only exists when all the elements of the map are move-assignable.
+ constexpr map& operator=(map&& other);
+
//! Equivalent to `hana::equal`
template <typename X, typename Y>
friend constexpr auto operator==(X&& x, Y&& y);
@@ -120,7 +131,7 @@ BOOST_HANA_NAMESPACE_BEGIN
};
#else
template <typename ...Pairs>
- using map = decltype(hana::make<map_tag>(std::declval<Pairs>()...));
+ using map = typename detail::make_map_type<Pairs...>::type;
#endif
//! Function object for creating a `hana::map`.
diff --git a/boost/hana/fwd/max.hpp b/boost/hana/fwd/max.hpp
index 7a63fbc270..e34d558e25 100644
--- a/boost/hana/fwd/max.hpp
+++ b/boost/hana/fwd/max.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::max`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/maximum.hpp b/boost/hana/fwd/maximum.hpp
index b725a68fa3..9a49e83d40 100644
--- a/boost/hana/fwd/maximum.hpp
+++ b/boost/hana/fwd/maximum.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::maximum`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/members.hpp b/boost/hana/fwd/members.hpp
index aaf9472faa..a9f2d82bfb 100644
--- a/boost/hana/fwd/members.hpp
+++ b/boost/hana/fwd/members.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::members`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/min.hpp b/boost/hana/fwd/min.hpp
index 2aeb7bda22..349787b571 100644
--- a/boost/hana/fwd/min.hpp
+++ b/boost/hana/fwd/min.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::min`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/minimum.hpp b/boost/hana/fwd/minimum.hpp
index 93926d92a6..df80196bc6 100644
--- a/boost/hana/fwd/minimum.hpp
+++ b/boost/hana/fwd/minimum.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::minimum`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/minus.hpp b/boost/hana/fwd/minus.hpp
index a113e47dbb..3b3b3ff428 100644
--- a/boost/hana/fwd/minus.hpp
+++ b/boost/hana/fwd/minus.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::minus`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/mod.hpp b/boost/hana/fwd/mod.hpp
index 1ed87eb5a5..c0872803fc 100644
--- a/boost/hana/fwd/mod.hpp
+++ b/boost/hana/fwd/mod.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::mod`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/monadic_compose.hpp b/boost/hana/fwd/monadic_compose.hpp
index e5edfcc133..e9adde1bc2 100644
--- a/boost/hana/fwd/monadic_compose.hpp
+++ b/boost/hana/fwd/monadic_compose.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::monadic_compose`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/monadic_fold_left.hpp b/boost/hana/fwd/monadic_fold_left.hpp
index 786019b0b4..c037989dea 100644
--- a/boost/hana/fwd/monadic_fold_left.hpp
+++ b/boost/hana/fwd/monadic_fold_left.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::monadic_fold_left`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/monadic_fold_right.hpp b/boost/hana/fwd/monadic_fold_right.hpp
index 692eacbdf4..2028e15369 100644
--- a/boost/hana/fwd/monadic_fold_right.hpp
+++ b/boost/hana/fwd/monadic_fold_right.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::monadic_fold_right`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/mult.hpp b/boost/hana/fwd/mult.hpp
index cc624e76f2..d322071d9c 100644
--- a/boost/hana/fwd/mult.hpp
+++ b/boost/hana/fwd/mult.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::mult`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/negate.hpp b/boost/hana/fwd/negate.hpp
index 2be58f2252..6c4f70da8d 100644
--- a/boost/hana/fwd/negate.hpp
+++ b/boost/hana/fwd/negate.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::negate`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/none.hpp b/boost/hana/fwd/none.hpp
index 158f4c93d7..d0d2da94a9 100644
--- a/boost/hana/fwd/none.hpp
+++ b/boost/hana/fwd/none.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::none`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/none_of.hpp b/boost/hana/fwd/none_of.hpp
index 2455f1a9da..3e57cf1d65 100644
--- a/boost/hana/fwd/none_of.hpp
+++ b/boost/hana/fwd/none_of.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::none_of`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/not.hpp b/boost/hana/fwd/not.hpp
index f343a417ab..08d19d2bd5 100644
--- a/boost/hana/fwd/not.hpp
+++ b/boost/hana/fwd/not.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::not_`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/not_equal.hpp b/boost/hana/fwd/not_equal.hpp
index 4c7bdbfbcf..7063a3796c 100644
--- a/boost/hana/fwd/not_equal.hpp
+++ b/boost/hana/fwd/not_equal.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::not_equal`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/one.hpp b/boost/hana/fwd/one.hpp
index 65df2bf3c4..d2c67b7228 100644
--- a/boost/hana/fwd/one.hpp
+++ b/boost/hana/fwd/one.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::one`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/optional.hpp b/boost/hana/fwd/optional.hpp
index 934eca809a..28bb68e8af 100644
--- a/boost/hana/fwd/optional.hpp
+++ b/boost/hana/fwd/optional.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::optional`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/or.hpp b/boost/hana/fwd/or.hpp
index 1d2ad1a348..c14efc8e34 100644
--- a/boost/hana/fwd/or.hpp
+++ b/boost/hana/fwd/or.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::or_`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/ordering.hpp b/boost/hana/fwd/ordering.hpp
index 6e9f25dfa0..78c9e2c3b8 100644
--- a/boost/hana/fwd/ordering.hpp
+++ b/boost/hana/fwd/ordering.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::ordering`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/pair.hpp b/boost/hana/fwd/pair.hpp
index 0a36da1875..897e87ad12 100644
--- a/boost/hana/fwd/pair.hpp
+++ b/boost/hana/fwd/pair.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::pair`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/partition.hpp b/boost/hana/fwd/partition.hpp
index 4b8cf00f18..b7a7d3a2ae 100644
--- a/boost/hana/fwd/partition.hpp
+++ b/boost/hana/fwd/partition.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::partition`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/permutations.hpp b/boost/hana/fwd/permutations.hpp
index af2805d333..7aeb27b2e8 100644
--- a/boost/hana/fwd/permutations.hpp
+++ b/boost/hana/fwd/permutations.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::permutations`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/plus.hpp b/boost/hana/fwd/plus.hpp
index e1a6e058f2..6d6cac82e2 100644
--- a/boost/hana/fwd/plus.hpp
+++ b/boost/hana/fwd/plus.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::plus`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/power.hpp b/boost/hana/fwd/power.hpp
index 77ae209a90..c94b841194 100644
--- a/boost/hana/fwd/power.hpp
+++ b/boost/hana/fwd/power.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::power`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/prefix.hpp b/boost/hana/fwd/prefix.hpp
index 515739f077..78592e11f2 100644
--- a/boost/hana/fwd/prefix.hpp
+++ b/boost/hana/fwd/prefix.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::prefix`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/prepend.hpp b/boost/hana/fwd/prepend.hpp
index 445dae921d..8bb44ea2db 100644
--- a/boost/hana/fwd/prepend.hpp
+++ b/boost/hana/fwd/prepend.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::prepend`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/product.hpp b/boost/hana/fwd/product.hpp
index f8a1c67f7d..96bbd77c4e 100644
--- a/boost/hana/fwd/product.hpp
+++ b/boost/hana/fwd/product.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::product`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/range.hpp b/boost/hana/fwd/range.hpp
index 4ddb5a96b8..82d0f75232 100644
--- a/boost/hana/fwd/range.hpp
+++ b/boost/hana/fwd/range.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::range`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/remove.hpp b/boost/hana/fwd/remove.hpp
index 7f9191d4ab..88254410a9 100644
--- a/boost/hana/fwd/remove.hpp
+++ b/boost/hana/fwd/remove.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::remove`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/remove_at.hpp b/boost/hana/fwd/remove_at.hpp
index 6e25e4db45..f997d6e4c5 100644
--- a/boost/hana/fwd/remove_at.hpp
+++ b/boost/hana/fwd/remove_at.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::remove_at` and `boost::hana::remove_at_c`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/remove_if.hpp b/boost/hana/fwd/remove_if.hpp
index 4d6a9722cc..590a6e195e 100644
--- a/boost/hana/fwd/remove_if.hpp
+++ b/boost/hana/fwd/remove_if.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::remove_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/remove_range.hpp b/boost/hana/fwd/remove_range.hpp
index 5274a0e579..1645cce598 100644
--- a/boost/hana/fwd/remove_range.hpp
+++ b/boost/hana/fwd/remove_range.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::remove_range` and `boost::hana::remove_range_c`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/repeat.hpp b/boost/hana/fwd/repeat.hpp
index dbb39eea0b..0151b5c9e0 100644
--- a/boost/hana/fwd/repeat.hpp
+++ b/boost/hana/fwd/repeat.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::repeat`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/replace.hpp b/boost/hana/fwd/replace.hpp
index 81eec5b1ae..6edb858a7f 100644
--- a/boost/hana/fwd/replace.hpp
+++ b/boost/hana/fwd/replace.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::replace`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/replace_if.hpp b/boost/hana/fwd/replace_if.hpp
index 36df3eb40a..e3fe882125 100644
--- a/boost/hana/fwd/replace_if.hpp
+++ b/boost/hana/fwd/replace_if.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::replace_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/replicate.hpp b/boost/hana/fwd/replicate.hpp
index 0580d90601..4861adabae 100644
--- a/boost/hana/fwd/replicate.hpp
+++ b/boost/hana/fwd/replicate.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::replicate`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/reverse.hpp b/boost/hana/fwd/reverse.hpp
index 0c5bb5c7f9..b47b610bb8 100644
--- a/boost/hana/fwd/reverse.hpp
+++ b/boost/hana/fwd/reverse.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::reverse`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/reverse_fold.hpp b/boost/hana/fwd/reverse_fold.hpp
index c5a770b576..607dd2dc4d 100644
--- a/boost/hana/fwd/reverse_fold.hpp
+++ b/boost/hana/fwd/reverse_fold.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::reverse_fold`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/scan_left.hpp b/boost/hana/fwd/scan_left.hpp
index 4ec8987a92..2418196d32 100644
--- a/boost/hana/fwd/scan_left.hpp
+++ b/boost/hana/fwd/scan_left.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::scan_left`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/scan_right.hpp b/boost/hana/fwd/scan_right.hpp
index f23dfd1104..c99cc911e9 100644
--- a/boost/hana/fwd/scan_right.hpp
+++ b/boost/hana/fwd/scan_right.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::scan_right`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/second.hpp b/boost/hana/fwd/second.hpp
index edbbaa36fe..6dc4623b79 100644
--- a/boost/hana/fwd/second.hpp
+++ b/boost/hana/fwd/second.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::second`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/set.hpp b/boost/hana/fwd/set.hpp
index 2b0fdc5284..55bd72d248 100644
--- a/boost/hana/fwd/set.hpp
+++ b/boost/hana/fwd/set.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::set`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -72,6 +72,10 @@ BOOST_HANA_NAMESPACE_BEGIN
#ifdef BOOST_HANA_DOXYGEN_INVOKED
template <typename implementation_defined>
struct set {
+ //! Default-construct a set. This constructor only exists when all the
+ //! elements of the set are default-constructible.
+ constexpr set() = default;
+
//! Copy-construct a set from another set. This constructor only
//! exists when all the elements of the set are copy-constructible.
constexpr set(set const& other) = default;
diff --git a/boost/hana/fwd/size.hpp b/boost/hana/fwd/size.hpp
index b3c4e3ba96..8999b91413 100644
--- a/boost/hana/fwd/size.hpp
+++ b/boost/hana/fwd/size.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::size`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/slice.hpp b/boost/hana/fwd/slice.hpp
index 82eae5b29a..f8dfafc02d 100644
--- a/boost/hana/fwd/slice.hpp
+++ b/boost/hana/fwd/slice.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::slice` and `boost::hana::slice_c`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/sort.hpp b/boost/hana/fwd/sort.hpp
index 3cb1fdabc7..c0d45aee23 100644
--- a/boost/hana/fwd/sort.hpp
+++ b/boost/hana/fwd/sort.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::sort`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/span.hpp b/boost/hana/fwd/span.hpp
index 2a46ebd88a..047b2bc174 100644
--- a/boost/hana/fwd/span.hpp
+++ b/boost/hana/fwd/span.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::span`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/string.hpp b/boost/hana/fwd/string.hpp
index c3476d7e72..ab23d52aea 100644
--- a/boost/hana/fwd/string.hpp
+++ b/boost/hana/fwd/string.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::string`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -106,6 +106,12 @@ BOOST_HANA_NAMESPACE_BEGIN
//! > a bit complicated for the time being.
template <typename implementation_defined>
struct string {
+ // Default-construct a `hana::string`; no-op since `hana::string` is stateless.
+ constexpr string() = default;
+
+ // Copy-construct a `hana::string`; no-op since `hana::string` is stateless.
+ constexpr string(string const&) = default;
+
//! Equivalent to `hana::equal`
template <typename X, typename Y>
friend constexpr auto operator==(X&& x, Y&& y);
diff --git a/boost/hana/fwd/suffix.hpp b/boost/hana/fwd/suffix.hpp
index ec3002aeef..331854fe5d 100644
--- a/boost/hana/fwd/suffix.hpp
+++ b/boost/hana/fwd/suffix.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::suffix`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/sum.hpp b/boost/hana/fwd/sum.hpp
index 273f43c77b..c565ecd7f7 100644
--- a/boost/hana/fwd/sum.hpp
+++ b/boost/hana/fwd/sum.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::sum`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/symmetric_difference.hpp b/boost/hana/fwd/symmetric_difference.hpp
index d23d637c30..2908daaeee 100644
--- a/boost/hana/fwd/symmetric_difference.hpp
+++ b/boost/hana/fwd/symmetric_difference.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::symmetric_difference`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/take_back.hpp b/boost/hana/fwd/take_back.hpp
index 60560aa3d9..fa4dde5e3c 100644
--- a/boost/hana/fwd/take_back.hpp
+++ b/boost/hana/fwd/take_back.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::take_back`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/take_front.hpp b/boost/hana/fwd/take_front.hpp
index fe46b35133..9ce3b9c030 100644
--- a/boost/hana/fwd/take_front.hpp
+++ b/boost/hana/fwd/take_front.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::take_front` and `boost::hana::take_front_c`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/take_while.hpp b/boost/hana/fwd/take_while.hpp
index 7807512cc4..29f1ba24e0 100644
--- a/boost/hana/fwd/take_while.hpp
+++ b/boost/hana/fwd/take_while.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::take_while`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/tap.hpp b/boost/hana/fwd/tap.hpp
index 0f186c021b..846c1d00e6 100644
--- a/boost/hana/fwd/tap.hpp
+++ b/boost/hana/fwd/tap.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::tap`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/then.hpp b/boost/hana/fwd/then.hpp
index 83768e6ffb..b4adf3d4fe 100644
--- a/boost/hana/fwd/then.hpp
+++ b/boost/hana/fwd/then.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::then`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/transform.hpp b/boost/hana/fwd/transform.hpp
index 5f2518db78..af645f3d23 100644
--- a/boost/hana/fwd/transform.hpp
+++ b/boost/hana/fwd/transform.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::transform`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/tuple.hpp b/boost/hana/fwd/tuple.hpp
index 1624b3d296..f51ab9ac22 100644
--- a/boost/hana/fwd/tuple.hpp
+++ b/boost/hana/fwd/tuple.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::tuple`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/type.hpp b/boost/hana/fwd/type.hpp
index d3390cf5bd..c3c220db78 100644
--- a/boost/hana/fwd/type.hpp
+++ b/boost/hana/fwd/type.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::type` and related utilities.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -37,18 +37,25 @@ BOOST_HANA_NAMESPACE_BEGIN
//!
//!
//! @note
- //! For subtle reasons having to do with ADL, the actual representation of
- //! `hana::type` is implementation-defined. In particular, `hana::type`
- //! may be a dependent type, so one should not attempt to do pattern
- //! matching on it. However, one can assume that `hana::type` _inherits_
- //! from `hana::basic_type`, which can be useful when declaring overloaded
- //! functions:
+ //! For subtle reasons, the actual representation of `hana::type` is
+ //! implementation-defined. In particular, `hana::type` may be a dependent
+ //! type, so one should not attempt to do pattern matching on it. However,
+ //! one can assume that `hana::type` _inherits_ from `hana::basic_type`,
+ //! which can be useful when declaring overloaded functions:
//! @code
//! template <typename T>
//! void f(hana::basic_type<T>) {
//! // do something with T
//! }
//! @endcode
+ //! The full story is that [ADL][] causes template arguments to be
+ //! instantiated. Hence, if `hana::type` were defined naively, expressions
+ //! like `hana::type<T>{} == hana::type<U>{}` would cause both `T` and `U`
+ //! to be instantiated. This is usually not a problem, except when `T` or
+ //! `U` should not be instantiated. To avoid these instantiations,
+ //! `hana::type` is implemented using some cleverness, and that is
+ //! why the representation is implementation-defined. When that
+ //! behavior is not required, `hana::basic_type` can be used instead.
//!
//!
//! @anchor type_lvalues_and_rvalues
@@ -86,6 +93,8 @@ BOOST_HANA_NAMESPACE_BEGIN
//! The hash of a type is just that type itself. In other words, `hash`
//! is the identity function on `hana::type`s.
//! @include example/type/hashable.cpp
+ //!
+ //! [ADL]: http://en.cppreference.com/w/cpp/language/adl
#ifdef BOOST_HANA_DOXYGEN_INVOKED
template <typename T>
struct type {
diff --git a/boost/hana/fwd/unfold_left.hpp b/boost/hana/fwd/unfold_left.hpp
index 3e68e549d5..d753222630 100644
--- a/boost/hana/fwd/unfold_left.hpp
+++ b/boost/hana/fwd/unfold_left.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::unfold_left`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/unfold_right.hpp b/boost/hana/fwd/unfold_right.hpp
index b688d7606f..53ee56fc48 100644
--- a/boost/hana/fwd/unfold_right.hpp
+++ b/boost/hana/fwd/unfold_right.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::unfold_right`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/union.hpp b/boost/hana/fwd/union.hpp
index 38df48e941..ccf539221f 100644
--- a/boost/hana/fwd/union.hpp
+++ b/boost/hana/fwd/union.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::union_`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/unique.hpp b/boost/hana/fwd/unique.hpp
index 4271f23a9e..5eab73eb3b 100644
--- a/boost/hana/fwd/unique.hpp
+++ b/boost/hana/fwd/unique.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::unique`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/unpack.hpp b/boost/hana/fwd/unpack.hpp
index 457cacea97..f66c29ae8b 100644
--- a/boost/hana/fwd/unpack.hpp
+++ b/boost/hana/fwd/unpack.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::unpack`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/value.hpp b/boost/hana/fwd/value.hpp
index 4a64507c7b..7db9384f77 100644
--- a/boost/hana/fwd/value.hpp
+++ b/boost/hana/fwd/value.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::value`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/while.hpp b/boost/hana/fwd/while.hpp
index e9efc4464d..14923797b5 100644
--- a/boost/hana/fwd/while.hpp
+++ b/boost/hana/fwd/while.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::while_`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/zero.hpp b/boost/hana/fwd/zero.hpp
index dc35dd4d6d..412614786d 100644
--- a/boost/hana/fwd/zero.hpp
+++ b/boost/hana/fwd/zero.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::zero`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/zip.hpp b/boost/hana/fwd/zip.hpp
index e5d1c8d178..505decfcf0 100644
--- a/boost/hana/fwd/zip.hpp
+++ b/boost/hana/fwd/zip.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::zip`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/zip_shortest.hpp b/boost/hana/fwd/zip_shortest.hpp
index 33dbd6220b..5f0622789d 100644
--- a/boost/hana/fwd/zip_shortest.hpp
+++ b/boost/hana/fwd/zip_shortest.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::zip_shortest`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/zip_shortest_with.hpp b/boost/hana/fwd/zip_shortest_with.hpp
index 65c2e2acda..47d5a43b61 100644
--- a/boost/hana/fwd/zip_shortest_with.hpp
+++ b/boost/hana/fwd/zip_shortest_with.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::zip_shortest_with`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/fwd/zip_with.hpp b/boost/hana/fwd/zip_with.hpp
index 19dd314aa6..3e153a3e6a 100644
--- a/boost/hana/fwd/zip_with.hpp
+++ b/boost/hana/fwd/zip_with.hpp
@@ -2,7 +2,7 @@
@file
Forward declares `boost::hana::zip_with`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/greater.hpp b/boost/hana/greater.hpp
index ee75bb806a..84f7e23a1a 100644
--- a/boost/hana/greater.hpp
+++ b/boost/hana/greater.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::greater`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/greater_equal.hpp b/boost/hana/greater_equal.hpp
index 116c890b49..e9b34d2587 100644
--- a/boost/hana/greater_equal.hpp
+++ b/boost/hana/greater_equal.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::greater_equal`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/group.hpp b/boost/hana/group.hpp
index 66f005a347..b21cd6b5f0 100644
--- a/boost/hana/group.hpp
+++ b/boost/hana/group.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::group`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -97,7 +97,7 @@ BOOST_HANA_NAMESPACE_BEGIN
}
static constexpr auto info = compute_info();
- static constexpr auto offsets = info.first;
+ static constexpr auto group_offsets = info.first;
static constexpr auto group_sizes = info.second;
template <typename S, typename Xs, std::size_t ...i>
@@ -106,7 +106,8 @@ BOOST_HANA_NAMESPACE_BEGIN
detail::get_subsequence_(
static_cast<Xs&&>(xs),
typename offset_by<
- offsets[i], std::make_index_sequence<group_sizes[i]>
+ group_offsets[i],
+ std::make_index_sequence<group_sizes[i]>
>::type{}
)...
);
diff --git a/boost/hana/if.hpp b/boost/hana/if.hpp
index f65b514be7..5d7f2bb969 100644
--- a/boost/hana/if.hpp
+++ b/boost/hana/if.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::if_`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -21,7 +21,7 @@ Distributed under the Boost Software License, Version 1.0.
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Cond, typename Then, typename Else>
- constexpr decltype(auto) if_t::operator()(Cond&& cond, Then&& then, Else&& else_) const {
+ constexpr decltype(auto) if_t::operator()(Cond&& cond, Then&& then_, Else&& else_) const {
using Bool = typename hana::tag_of<Cond>::type;
using If = BOOST_HANA_DISPATCH_IF(if_impl<Bool>,
hana::Logical<Bool>::value
@@ -33,7 +33,7 @@ BOOST_HANA_NAMESPACE_BEGIN
#endif
return If::apply(static_cast<Cond&&>(cond),
- static_cast<Then&&>(then),
+ static_cast<Then&&>(then_),
static_cast<Else&&>(else_));
}
//! @endcond
diff --git a/boost/hana/insert.hpp b/boost/hana/insert.hpp
index 706549c5d6..3752a64a29 100644
--- a/boost/hana/insert.hpp
+++ b/boost/hana/insert.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::insert`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/insert_range.hpp b/boost/hana/insert_range.hpp
index a5e86a51a5..26ad8f765e 100644
--- a/boost/hana/insert_range.hpp
+++ b/boost/hana/insert_range.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::insert_range`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/integral_constant.hpp b/boost/hana/integral_constant.hpp
index 2d8f4df7ca..edabfe454c 100644
--- a/boost/hana/integral_constant.hpp
+++ b/boost/hana/integral_constant.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::integral_constant`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/intersection.hpp b/boost/hana/intersection.hpp
index 16d7d211be..a9859d8f42 100644
--- a/boost/hana/intersection.hpp
+++ b/boost/hana/intersection.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::intersection`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/intersperse.hpp b/boost/hana/intersperse.hpp
index 2ef8eb329c..13e8240a13 100644
--- a/boost/hana/intersperse.hpp
+++ b/boost/hana/intersperse.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::intersperse`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/is_disjoint.hpp b/boost/hana/is_disjoint.hpp
index dcea16c89b..c4ffc73121 100644
--- a/boost/hana/is_disjoint.hpp
+++ b/boost/hana/is_disjoint.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::is_disjoint`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/is_empty.hpp b/boost/hana/is_empty.hpp
index ac1051914b..a8b68fa61a 100644
--- a/boost/hana/is_empty.hpp
+++ b/boost/hana/is_empty.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::is_empty`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/is_subset.hpp b/boost/hana/is_subset.hpp
index 546bc9baa5..7ef3e2bed5 100644
--- a/boost/hana/is_subset.hpp
+++ b/boost/hana/is_subset.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::is_subset`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/keys.hpp b/boost/hana/keys.hpp
index d6d521b7e2..b27be1d756 100644
--- a/boost/hana/keys.hpp
+++ b/boost/hana/keys.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::keys`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/lazy.hpp b/boost/hana/lazy.hpp
index 073fbca5af..5cb9a8a3ab 100644
--- a/boost/hana/lazy.hpp
+++ b/boost/hana/lazy.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::lazy`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -74,7 +74,7 @@ BOOST_HANA_NAMESPACE_BEGIN
X, typename detail::decay<Args>::type...
> operator()(Args&& ...args) const& {
return {detail::lazy_secret{},
- hana::get_impl<0>(storage_), static_cast<Args&&>(args)...};
+ hana::at_c<0>(storage_), static_cast<Args&&>(args)...};
}
template <typename ...Args>
@@ -83,7 +83,7 @@ BOOST_HANA_NAMESPACE_BEGIN
X, typename detail::decay<Args>::type...
> operator()(Args&& ...args) && {
return {detail::lazy_secret{},
- static_cast<X&&>(hana::get_impl<0>(storage_)),
+ static_cast<X&&>(hana::at_c<0>(storage_)),
static_cast<Args&&>(args)...
};
}
@@ -117,39 +117,39 @@ BOOST_HANA_NAMESPACE_BEGIN
template <std::size_t ...n, typename F, typename ...Args>
static constexpr decltype(auto)
apply(lazy_apply_t<std::index_sequence<n...>, F, Args...> const& expr) {
- return hana::get_impl<0>(expr.storage_)(
- hana::get_impl<n+1>(expr.storage_)...
+ return hana::at_c<0>(expr.storage_)(
+ hana::at_c<n+1>(expr.storage_)...
);
}
template <std::size_t ...n, typename F, typename ...Args>
static constexpr decltype(auto)
apply(lazy_apply_t<std::index_sequence<n...>, F, Args...>& expr) {
- return hana::get_impl<0>(expr.storage_)(
- hana::get_impl<n+1>(expr.storage_)...
+ return hana::at_c<0>(expr.storage_)(
+ hana::at_c<n+1>(expr.storage_)...
);
}
template <std::size_t ...n, typename F, typename ...Args>
static constexpr decltype(auto)
apply(lazy_apply_t<std::index_sequence<n...>, F, Args...>&& expr) {
- return static_cast<F&&>(hana::get_impl<0>(expr.storage_))(
- static_cast<Args&&>(hana::get_impl<n+1>(expr.storage_))...
+ return static_cast<F&&>(hana::at_c<0>(expr.storage_))(
+ static_cast<Args&&>(hana::at_c<n+1>(expr.storage_))...
);
}
// lazy_value_t
template <typename X>
static constexpr X const& apply(lazy_value_t<X> const& expr)
- { return hana::get_impl<0>(expr.storage_); }
+ { return hana::at_c<0>(expr.storage_); }
template <typename X>
static constexpr X& apply(lazy_value_t<X>& expr)
- { return hana::get_impl<0>(expr.storage_); }
+ { return hana::at_c<0>(expr.storage_); }
template <typename X>
static constexpr X apply(lazy_value_t<X>&& expr)
- { return static_cast<X&&>(hana::get_impl<0>(expr.storage_)); }
+ { return static_cast<X&&>(hana::at_c<0>(expr.storage_)); }
};
//////////////////////////////////////////////////////////////////////////
diff --git a/boost/hana/length.hpp b/boost/hana/length.hpp
index f8493a77c5..44c195b390 100644
--- a/boost/hana/length.hpp
+++ b/boost/hana/length.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::length`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/less.hpp b/boost/hana/less.hpp
index eff6d3709b..05cceabb1d 100644
--- a/boost/hana/less.hpp
+++ b/boost/hana/less.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::less`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -103,8 +103,8 @@ BOOST_HANA_NAMESPACE_BEGIN
>> {
template <typename X, typename Y>
static constexpr auto apply(X const&, Y const&) {
- constexpr auto less = hana::less(hana::value<X>(), hana::value<Y>());
- constexpr bool truth_value = hana::if_(less, true, false);
+ constexpr auto is_less = hana::less(hana::value<X>(), hana::value<Y>());
+ constexpr bool truth_value = hana::if_(is_less, true, false);
return hana::bool_c<truth_value>;
}
};
diff --git a/boost/hana/less_equal.hpp b/boost/hana/less_equal.hpp
index 3a04f9b3c5..d3d0efe911 100644
--- a/boost/hana/less_equal.hpp
+++ b/boost/hana/less_equal.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::less_equal`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/lexicographical_compare.hpp b/boost/hana/lexicographical_compare.hpp
index bb2ca15a43..e8363ad9f1 100644
--- a/boost/hana/lexicographical_compare.hpp
+++ b/boost/hana/lexicographical_compare.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::lexicographical_compare`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/lift.hpp b/boost/hana/lift.hpp
index a91c43bacc..b8ab3431c2 100644
--- a/boost/hana/lift.hpp
+++ b/boost/hana/lift.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::lift`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/map.hpp b/boost/hana/map.hpp
index 3161d9b777..cccf6cf3b9 100644
--- a/boost/hana/map.hpp
+++ b/boost/hana/map.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::map`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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,6 +27,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/detail/fast_and.hpp>
#include <boost/hana/detail/has_duplicates.hpp>
#include <boost/hana/detail/hash_table.hpp>
+#include <boost/hana/detail/intrinsics.hpp>
#include <boost/hana/detail/operators/adl.hpp>
#include <boost/hana/detail/operators/comparable.hpp>
#include <boost/hana/detail/operators/searchable.hpp>
@@ -73,6 +74,51 @@ BOOST_HANA_NAMESPACE_BEGIN
//////////////////////////////////////////////////////////////////////////
//! @cond
namespace detail {
+ template <typename ...>
+ struct storage_is_default_constructible;
+ template <typename ...T>
+ struct storage_is_default_constructible<hana::basic_tuple<T...>> {
+ static constexpr bool value = detail::fast_and<
+ BOOST_HANA_TT_IS_CONSTRUCTIBLE(T)...
+ >::value;
+ };
+
+ template <typename ...>
+ struct storage_is_copy_constructible;
+ template <typename ...T>
+ struct storage_is_copy_constructible<hana::basic_tuple<T...>> {
+ static constexpr bool value = detail::fast_and<
+ BOOST_HANA_TT_IS_CONSTRUCTIBLE(T, T const&)...
+ >::value;
+ };
+
+ template <typename ...>
+ struct storage_is_move_constructible;
+ template <typename ...T>
+ struct storage_is_move_constructible<hana::basic_tuple<T...>> {
+ static constexpr bool value = detail::fast_and<
+ BOOST_HANA_TT_IS_CONSTRUCTIBLE(T, T&&)...
+ >::value;
+ };
+
+ template <typename ...>
+ struct storage_is_copy_assignable;
+ template <typename ...T>
+ struct storage_is_copy_assignable<hana::basic_tuple<T...>> {
+ static constexpr bool value = detail::fast_and<
+ BOOST_HANA_TT_IS_ASSIGNABLE(T, T const&)...
+ >::value;
+ };
+
+ template <typename ...>
+ struct storage_is_move_assignable;
+ template <typename ...T>
+ struct storage_is_move_assignable<hana::basic_tuple<T...>> {
+ static constexpr bool value = detail::fast_and<
+ BOOST_HANA_TT_IS_ASSIGNABLE(T, T&&)...
+ >::value;
+ };
+
template <typename HashTable, typename Storage>
struct map_impl
: detail::searchable_operators<map_impl<HashTable, Storage>>
@@ -99,16 +145,62 @@ BOOST_HANA_NAMESPACE_BEGIN
: storage(static_cast<Storage&&>(xs))
{ }
- constexpr map_impl() = default;
- constexpr map_impl(map_impl const& other) = default;
- constexpr map_impl(map_impl&& other) = default;
+ template <typename ...Dummy, typename = typename std::enable_if<
+ detail::storage_is_default_constructible<Storage, Dummy...>::value
+ >::type>
+ constexpr map_impl()
+ : storage()
+ { }
+
+ template <typename ...Dummy, typename = typename std::enable_if<
+ detail::storage_is_copy_constructible<Storage, Dummy...>::value
+ >::type>
+ constexpr map_impl(map_impl const& other)
+ : storage(other.storage)
+ { }
+
+ template <typename ...Dummy, typename = typename std::enable_if<
+ detail::storage_is_move_constructible<Storage, Dummy...>::value
+ >::type>
+ constexpr map_impl(map_impl&& other)
+ : storage(static_cast<Storage&&>(other.storage))
+ { }
+
+ template <typename ...Dummy, typename = typename std::enable_if<
+ detail::storage_is_move_assignable<Storage, Dummy...>::value
+ >::type>
+ constexpr map_impl& operator=(map_impl&& other) {
+ storage = static_cast<Storage&&>(other.storage);
+ return *this;
+ }
+
+ template <typename ...Dummy, typename = typename std::enable_if<
+ detail::storage_is_copy_assignable<Storage, Dummy...>::value
+ >::type>
+ constexpr map_impl& operator=(map_impl const& other) {
+ storage = other.storage;
+ return *this;
+ }
+
+ // Prevent the compiler from defining the default copy and move
+ // constructors, which interfere with the SFINAE above.
+ ~map_impl() = default;
};
//! @endcond
template <typename Storage>
struct KeyAtIndex {
template <std::size_t i>
- using apply = decltype(hana::first(hana::get_impl<i>(std::declval<Storage>())));
+ using apply = decltype(hana::first(hana::at_c<i>(std::declval<Storage>())));
+ };
+
+ template <typename ...Pairs>
+ struct make_map_type {
+ using Storage = hana::basic_tuple<Pairs...>;
+ using HashTable = typename detail::make_hash_table<
+ detail::KeyAtIndex<Storage>::template apply, sizeof...(Pairs)
+ >::type;
+ using type = detail::map_impl<HashTable, Storage>;
};
}
@@ -146,14 +238,8 @@ BOOST_HANA_NAMESPACE_BEGIN
"hana::make_map({keys, values}...) requires all the keys to have different hashes");
#endif
- using Storage = hana::basic_tuple<typename detail::decay<Pairs>::type...>;
- using HashTable = typename detail::make_hash_table<
- detail::KeyAtIndex<Storage>::template apply, sizeof...(Pairs)
- >::type;
-
- return detail::map_impl<HashTable, Storage>{
- hana::make_basic_tuple(static_cast<Pairs&&>(pairs)...)
- };
+ using Map = typename detail::make_map_type<typename detail::decay<Pairs>::type...>::type;
+ return Map{hana::make_basic_tuple(static_cast<Pairs&&>(pairs)...)};
}
};
@@ -251,10 +337,20 @@ BOOST_HANA_NAMESPACE_BEGIN
}
template <typename Map, typename Key>
- static constexpr auto apply(Map&& map, Key const& key) {
- constexpr bool contains = hana::value<decltype(hana::contains(map, key))>();
+ static constexpr auto apply_impl(Map&& map, Key const& key, hana::false_) {
return erase_key_helper(static_cast<Map&&>(map), key,
- hana::bool_c<contains>);
+ hana::contains(map, key));
+ }
+
+ template <typename Map, typename Key>
+ static constexpr auto apply_impl(Map&& map, Key const&, hana::true_) {
+ return static_cast<Map&&>(map);
+ }
+
+ template <typename Map, typename Key>
+ static constexpr auto apply(Map&& map, Key const& key) {
+ constexpr bool is_empty = decltype(hana::length(map))::value == 0;
+ return apply_impl(static_cast<Map&&>(map), key, hana::bool_<is_empty>{});
}
};
@@ -326,6 +422,20 @@ BOOST_HANA_NAMESPACE_BEGIN
};
template <>
+ struct contains_impl<map_tag> {
+ template <typename Map, typename Key>
+ static constexpr auto apply(Map const&, Key const&) {
+ using RawMap = typename std::remove_reference<Map>::type;
+ using HashTable = typename RawMap::hash_table_type;
+ using Storage = typename RawMap::storage_type;
+ using MaybeIndex = typename detail::find_index<
+ HashTable, Key, detail::KeyAtIndex<Storage>::template apply
+ >::type;
+ return hana::bool_<!decltype(hana::is_nothing(MaybeIndex{}))::value>{};
+ }
+ };
+
+ template <>
struct any_of_impl<map_tag> {
template <typename M, typename Pred>
static constexpr auto apply(M const& map, Pred const& pred)
diff --git a/boost/hana/max.hpp b/boost/hana/max.hpp
index b470c92e71..80889a791c 100644
--- a/boost/hana/max.hpp
+++ b/boost/hana/max.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::max`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/maximum.hpp b/boost/hana/maximum.hpp
index 36eaf1008d..14cb7abfd4 100644
--- a/boost/hana/maximum.hpp
+++ b/boost/hana/maximum.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::maximum`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/members.hpp b/boost/hana/members.hpp
index ffa933bfe8..13a5209288 100644
--- a/boost/hana/members.hpp
+++ b/boost/hana/members.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::members`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/min.hpp b/boost/hana/min.hpp
index 08f4cd9738..f8c887147b 100644
--- a/boost/hana/min.hpp
+++ b/boost/hana/min.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::min`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/minimum.hpp b/boost/hana/minimum.hpp
index 96b2444b6b..8b6f41d8c8 100644
--- a/boost/hana/minimum.hpp
+++ b/boost/hana/minimum.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::minimum`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/minus.hpp b/boost/hana/minus.hpp
index 067c3665c8..007a3ec24e 100644
--- a/boost/hana/minus.hpp
+++ b/boost/hana/minus.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::minus`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/mod.hpp b/boost/hana/mod.hpp
index 052df99ac9..f64b12f211 100644
--- a/boost/hana/mod.hpp
+++ b/boost/hana/mod.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::mod`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/monadic_compose.hpp b/boost/hana/monadic_compose.hpp
index 5bd8c5b8e4..064bfc24d3 100644
--- a/boost/hana/monadic_compose.hpp
+++ b/boost/hana/monadic_compose.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::monadic_compose`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/monadic_fold_left.hpp b/boost/hana/monadic_fold_left.hpp
index 7f28f9e508..e06c405604 100644
--- a/boost/hana/monadic_fold_left.hpp
+++ b/boost/hana/monadic_fold_left.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::monadic_fold_left`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/monadic_fold_right.hpp b/boost/hana/monadic_fold_right.hpp
index 46fb450439..7026b058c3 100644
--- a/boost/hana/monadic_fold_right.hpp
+++ b/boost/hana/monadic_fold_right.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::monadic_fold_right`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/mult.hpp b/boost/hana/mult.hpp
index 248607bc1d..9eb89a0cf2 100644
--- a/boost/hana/mult.hpp
+++ b/boost/hana/mult.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::mult`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/negate.hpp b/boost/hana/negate.hpp
index f0986f6fac..2b87e7d6a6 100644
--- a/boost/hana/negate.hpp
+++ b/boost/hana/negate.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::negate`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/none.hpp b/boost/hana/none.hpp
index 2079fc2efb..0d8d499dfe 100644
--- a/boost/hana/none.hpp
+++ b/boost/hana/none.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::none`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/none_of.hpp b/boost/hana/none_of.hpp
index 2c1fbec1d0..4cf3ffd2d9 100644
--- a/boost/hana/none_of.hpp
+++ b/boost/hana/none_of.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::none_of`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/not.hpp b/boost/hana/not.hpp
index 87ff508b29..2475f637f1 100644
--- a/boost/hana/not.hpp
+++ b/boost/hana/not.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::not_`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/not_equal.hpp b/boost/hana/not_equal.hpp
index 891bab7499..099574bdd0 100644
--- a/boost/hana/not_equal.hpp
+++ b/boost/hana/not_equal.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::not_equal`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/one.hpp b/boost/hana/one.hpp
index 47b902da60..b8d759b8c0 100644
--- a/boost/hana/one.hpp
+++ b/boost/hana/one.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::one`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/optional.hpp b/boost/hana/optional.hpp
index f99a489d3d..b3fe78b645 100644
--- a/boost/hana/optional.hpp
+++ b/boost/hana/optional.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::optional`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/or.hpp b/boost/hana/or.hpp
index a97510a474..b6aceac0c1 100644
--- a/boost/hana/or.hpp
+++ b/boost/hana/or.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::or_`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/ordering.hpp b/boost/hana/ordering.hpp
index 0be8bcaf6a..2e8294a892 100644
--- a/boost/hana/ordering.hpp
+++ b/boost/hana/ordering.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::ordering`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/pair.hpp b/boost/hana/pair.hpp
index 5a4bf87e23..75cd9e287b 100644
--- a/boost/hana/pair.hpp
+++ b/boost/hana/pair.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::pair`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -12,9 +12,9 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/fwd/pair.hpp>
-#include <boost/hana/basic_tuple.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/detail/ebo.hpp>
#include <boost/hana/detail/intrinsics.hpp>
#include <boost/hana/detail/operators/adl.hpp>
#include <boost/hana/detail/operators/comparable.hpp>
@@ -28,26 +28,37 @@ Distributed under the Boost Software License, Version 1.0.
BOOST_HANA_NAMESPACE_BEGIN
+ namespace detail {
+ template <int> struct pix; // pair index
+ }
+
//////////////////////////////////////////////////////////////////////////
// pair
//////////////////////////////////////////////////////////////////////////
//! @cond
template <typename First, typename Second>
- struct pair : detail::operators::adl<pair<First, Second>> {
+ struct pair : detail::operators::adl<pair<First, Second>>
+ , private detail::ebo<detail::pix<0>, First>
+ , private detail::ebo<detail::pix<1>, Second>
+ {
+ // Default constructor
template <typename ...dummy, typename = typename std::enable_if<
BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, dummy...) &&
BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, dummy...)
>::type>
constexpr pair()
- : storage_()
+ : detail::ebo<detail::pix<0>, First>()
+ , detail::ebo<detail::pix<1>, Second>()
{ }
+ // Variadic constructors
template <typename ...dummy, typename = typename std::enable_if<
BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, First const&, dummy...) &&
BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, Second const&, dummy...)
>::type>
- constexpr pair(First const& first, Second const& second)
- : storage_{first, second}
+ constexpr pair(First const& fst, Second const& snd)
+ : detail::ebo<detail::pix<0>, First>(fst)
+ , detail::ebo<detail::pix<1>, Second>(snd)
{ }
template <typename T, typename U, typename = typename std::enable_if<
@@ -55,34 +66,43 @@ BOOST_HANA_NAMESPACE_BEGIN
BOOST_HANA_TT_IS_CONVERTIBLE(U&&, Second)
>::type>
constexpr pair(T&& t, U&& u)
- : storage_{static_cast<T&&>(t), static_cast<U&&>(u)}
+ : detail::ebo<detail::pix<0>, First>(static_cast<T&&>(t))
+ , detail::ebo<detail::pix<1>, Second>(static_cast<U&&>(u))
{ }
+
+ // Possibly converting copy and move constructors
template <typename T, typename U, typename = typename std::enable_if<
+ BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, T const&) &&
+ BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, U const&) &&
BOOST_HANA_TT_IS_CONVERTIBLE(T const&, First) &&
BOOST_HANA_TT_IS_CONVERTIBLE(U const&, Second)
>::type>
constexpr pair(pair<T, U> const& other)
- : storage_{hana::get_impl<0>(other.storage_),
- hana::get_impl<1>(other.storage_)}
+ : 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))
{ }
template <typename T, typename U, typename = typename std::enable_if<
+ BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, T&&) &&
+ BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, U&&) &&
BOOST_HANA_TT_IS_CONVERTIBLE(T&&, First) &&
BOOST_HANA_TT_IS_CONVERTIBLE(U&&, Second)
>::type>
constexpr pair(pair<T, U>&& other)
- : storage_{static_cast<T&&>(hana::get_impl<0>(other.storage_)),
- static_cast<U&&>(hana::get_impl<1>(other.storage_))}
+ : 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)))
{ }
+
+ // Copy and move assignment
template <typename T, typename U, typename = typename std::enable_if<
BOOST_HANA_TT_IS_ASSIGNABLE(First&, T const&) &&
BOOST_HANA_TT_IS_ASSIGNABLE(Second&, U const&)
>::type>
constexpr pair& operator=(pair<T, U> const& other) {
- hana::get_impl<0>(storage_) = hana::get_impl<0>(other.storage_);
- hana::get_impl<1>(storage_) = hana::get_impl<1>(other.storage_);
+ 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);
return *this;
}
@@ -91,16 +111,26 @@ BOOST_HANA_NAMESPACE_BEGIN
BOOST_HANA_TT_IS_ASSIGNABLE(Second&, U&&)
>::type>
constexpr pair& operator=(pair<T, U>&& other) {
- hana::get_impl<0>(storage_) = static_cast<T&&>(hana::get_impl<0>(other.storage_));
- hana::get_impl<1>(storage_) = static_cast<U&&>(hana::get_impl<1>(other.storage_));
+ 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));
return *this;
}
- using hana_tag = pair_tag;
- basic_tuple<First, Second> storage_;
+ // Prevent the compiler from defining the default copy and move
+ // constructors, which interfere with the SFINAE above.
+ ~pair() = default;
+
+ friend struct first_impl<pair_tag>;
+ friend struct second_impl<pair_tag>;
+ template <typename F, typename S> friend struct pair;
};
//! @endcond
+ template <typename First, typename Second>
+ struct tag_of<pair<First, Second>> {
+ using type = pair_tag;
+ };
+
//////////////////////////////////////////////////////////////////////////
// Operators
//////////////////////////////////////////////////////////////////////////
@@ -131,16 +161,46 @@ BOOST_HANA_NAMESPACE_BEGIN
template <>
struct first_impl<pair_tag> {
- template <typename P>
- static constexpr decltype(auto) apply(P&& p)
- { return hana::get_impl<0>(static_cast<P&&>(p).storage_); }
+ template <typename First, typename Second>
+ static constexpr decltype(auto) apply(hana::pair<First, Second>& p) {
+ return detail::ebo_get<detail::pix<0>>(
+ static_cast<detail::ebo<detail::pix<0>, First>&>(p)
+ );
+ }
+ template <typename First, typename Second>
+ static constexpr decltype(auto) apply(hana::pair<First, Second> const& p) {
+ return detail::ebo_get<detail::pix<0>>(
+ static_cast<detail::ebo<detail::pix<0>, First> const&>(p)
+ );
+ }
+ template <typename First, typename Second>
+ static constexpr decltype(auto) apply(hana::pair<First, Second>&& p) {
+ return detail::ebo_get<detail::pix<0>>(
+ static_cast<detail::ebo<detail::pix<0>, First>&&>(p)
+ );
+ }
};
template <>
struct second_impl<pair_tag> {
- template <typename P>
- static constexpr decltype(auto) apply(P&& p)
- { return hana::get_impl<1>(static_cast<P&&>(p).storage_); }
+ template <typename First, typename Second>
+ static constexpr decltype(auto) apply(hana::pair<First, Second>& p) {
+ return detail::ebo_get<detail::pix<1>>(
+ static_cast<detail::ebo<detail::pix<1>, Second>&>(p)
+ );
+ }
+ template <typename First, typename Second>
+ static constexpr decltype(auto) apply(hana::pair<First, Second> const& p) {
+ return detail::ebo_get<detail::pix<1>>(
+ static_cast<detail::ebo<detail::pix<1>, Second> const&>(p)
+ );
+ }
+ template <typename First, typename Second>
+ static constexpr decltype(auto) apply(hana::pair<First, Second>&& p) {
+ return detail::ebo_get<detail::pix<1>>(
+ static_cast<detail::ebo<detail::pix<1>, Second>&&>(p)
+ );
+ }
};
BOOST_HANA_NAMESPACE_END
diff --git a/boost/hana/partition.hpp b/boost/hana/partition.hpp
index 00ce243081..fdea39bcf5 100644
--- a/boost/hana/partition.hpp
+++ b/boost/hana/partition.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::partition`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -72,16 +72,16 @@ BOOST_HANA_NAMESPACE_BEGIN
return indices;
}
- static constexpr auto left = compute_left();
- static constexpr auto right = compute_right();
+ static constexpr auto left_indices = compute_left();
+ static constexpr auto right_indices = compute_right();
template <typename S, typename Xs, std::size_t ...l, std::size_t ...r>
static constexpr auto apply(Xs&& xs, std::index_sequence<l...>,
std::index_sequence<r...>)
{
return hana::make<hana::pair_tag>(
- hana::make<S>(hana::at_c<left[l]>(static_cast<Xs&&>(xs))...),
- hana::make<S>(hana::at_c<right[r]>(static_cast<Xs&&>(xs))...)
+ hana::make<S>(hana::at_c<left_indices[l]>(static_cast<Xs&&>(xs))...),
+ hana::make<S>(hana::at_c<right_indices[r]>(static_cast<Xs&&>(xs))...)
);
}
};
diff --git a/boost/hana/permutations.hpp b/boost/hana/permutations.hpp
index 52052ff03d..601bd71889 100644
--- a/boost/hana/permutations.hpp
+++ b/boost/hana/permutations.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::permutations`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/plus.hpp b/boost/hana/plus.hpp
index 65a2cc99d5..bc916773a7 100644
--- a/boost/hana/plus.hpp
+++ b/boost/hana/plus.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::plus`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/power.hpp b/boost/hana/power.hpp
index b6f6de10a9..2a69ebfcaa 100644
--- a/boost/hana/power.hpp
+++ b/boost/hana/power.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::power`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/prefix.hpp b/boost/hana/prefix.hpp
index 64f3bfb984..e8b0c21947 100644
--- a/boost/hana/prefix.hpp
+++ b/boost/hana/prefix.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::prefix`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/prepend.hpp b/boost/hana/prepend.hpp
index c4f5f0e0e3..825d0b02f6 100644
--- a/boost/hana/prepend.hpp
+++ b/boost/hana/prepend.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::prepend`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/product.hpp b/boost/hana/product.hpp
index e6e584205a..8d3bad9fc3 100644
--- a/boost/hana/product.hpp
+++ b/boost/hana/product.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::product`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/range.hpp b/boost/hana/range.hpp
index ecddc7da8e..96a9d02e6a 100644
--- a/boost/hana/range.hpp
+++ b/boost/hana/range.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::range`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/remove.hpp b/boost/hana/remove.hpp
index 8472eb3c48..7d2925d38e 100644
--- a/boost/hana/remove.hpp
+++ b/boost/hana/remove.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::remove`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/remove_at.hpp b/boost/hana/remove_at.hpp
index 4ee061857d..490ebe8c10 100644
--- a/boost/hana/remove_at.hpp
+++ b/boost/hana/remove_at.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::remove_at` and `boost::hana::remove_at_c`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/remove_if.hpp b/boost/hana/remove_if.hpp
index fb85c3d424..b379957f3b 100644
--- a/boost/hana/remove_if.hpp
+++ b/boost/hana/remove_if.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::remove_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/remove_range.hpp b/boost/hana/remove_range.hpp
index d9fd3c1476..5e46f8ae77 100644
--- a/boost/hana/remove_range.hpp
+++ b/boost/hana/remove_range.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::remove_range` and `boost::hana::remove_range_c`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/repeat.hpp b/boost/hana/repeat.hpp
index 20184f89a1..71854dadbe 100644
--- a/boost/hana/repeat.hpp
+++ b/boost/hana/repeat.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::repeat`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/replace.hpp b/boost/hana/replace.hpp
index 3ef6528116..f797f6de2a 100644
--- a/boost/hana/replace.hpp
+++ b/boost/hana/replace.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::replace`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/replace_if.hpp b/boost/hana/replace_if.hpp
index 4d4490614d..026dd61354 100644
--- a/boost/hana/replace_if.hpp
+++ b/boost/hana/replace_if.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::replace_if`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/replicate.hpp b/boost/hana/replicate.hpp
index 1f73abc280..f04c4d8a44 100644
--- a/boost/hana/replicate.hpp
+++ b/boost/hana/replicate.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::replicate`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/reverse.hpp b/boost/hana/reverse.hpp
index d0156d076c..3e4126963f 100644
--- a/boost/hana/reverse.hpp
+++ b/boost/hana/reverse.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::reverse`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/reverse_fold.hpp b/boost/hana/reverse_fold.hpp
index 1cf07f931f..5735a423dd 100644
--- a/boost/hana/reverse_fold.hpp
+++ b/boost/hana/reverse_fold.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::reverse_fold`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/scan_left.hpp b/boost/hana/scan_left.hpp
index 1660e086f1..2ce4eb5d9d 100644
--- a/boost/hana/scan_left.hpp
+++ b/boost/hana/scan_left.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::scan_left`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/scan_right.hpp b/boost/hana/scan_right.hpp
index 3a8a11d435..a24eb145ca 100644
--- a/boost/hana/scan_right.hpp
+++ b/boost/hana/scan_right.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::scan_right`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/second.hpp b/boost/hana/second.hpp
index e5c28c9036..f17e7a67bf 100644
--- a/boost/hana/second.hpp
+++ b/boost/hana/second.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::second`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/set.hpp b/boost/hana/set.hpp
index c40547b77b..58979ed47f 100644
--- a/boost/hana/set.hpp
+++ b/boost/hana/set.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::set`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -72,6 +72,7 @@ BOOST_HANA_NAMESPACE_BEGIN
: storage(static_cast<tuple<Xs...>&&>(xs))
{ }
+ constexpr set() = default;
constexpr set(set const& other) = default;
constexpr set(set&& other) = default;
};
diff --git a/boost/hana/size.hpp b/boost/hana/size.hpp
index 8f3ba09961..762349cb62 100644
--- a/boost/hana/size.hpp
+++ b/boost/hana/size.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::size`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/slice.hpp b/boost/hana/slice.hpp
index 81eac951b1..2cc4c7209d 100644
--- a/boost/hana/slice.hpp
+++ b/boost/hana/slice.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::slice` and `boost::hana::slice_c`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/sort.hpp b/boost/hana/sort.hpp
index 3e6edb2cbd..65d6d27da3 100644
--- a/boost/hana/sort.hpp
+++ b/boost/hana/sort.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::sort`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/span.hpp b/boost/hana/span.hpp
index 8a5f02ef36..2219749b05 100644
--- a/boost/hana/span.hpp
+++ b/boost/hana/span.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::span`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/string.hpp b/boost/hana/string.hpp
index a1b97d2cbb..f9f6cae8e9 100644
--- a/boost/hana/string.hpp
+++ b/boost/hana/string.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::string`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/suffix.hpp b/boost/hana/suffix.hpp
index aca7064016..68a344db6e 100644
--- a/boost/hana/suffix.hpp
+++ b/boost/hana/suffix.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::suffix`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/sum.hpp b/boost/hana/sum.hpp
index 58713290b6..5c86dafdde 100644
--- a/boost/hana/sum.hpp
+++ b/boost/hana/sum.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::sum`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/symmetric_difference.hpp b/boost/hana/symmetric_difference.hpp
index f753c99561..1ca56d3019 100644
--- a/boost/hana/symmetric_difference.hpp
+++ b/boost/hana/symmetric_difference.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::symmetric_difference`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/take_back.hpp b/boost/hana/take_back.hpp
index 9a12d93b23..e838d0ac14 100644
--- a/boost/hana/take_back.hpp
+++ b/boost/hana/take_back.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::take_back`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -57,10 +57,10 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename Xs, typename N>
static constexpr auto apply(Xs&& xs, N const&) {
constexpr std::size_t n = N::value;
- constexpr std::size_t size = decltype(hana::length(xs))::value;
- constexpr std::size_t start = n < size ? size - n : 0;
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ constexpr std::size_t start = n < len ? len - n : 0;
return take_back_helper<start>(static_cast<Xs&&>(xs),
- std::make_index_sequence<(n < size ? n : size)>{});
+ std::make_index_sequence<(n < len ? n : len)>{});
}
};
BOOST_HANA_NAMESPACE_END
diff --git a/boost/hana/take_front.hpp b/boost/hana/take_front.hpp
index 65c851aaf4..b32fbb6e50 100644
--- a/boost/hana/take_front.hpp
+++ b/boost/hana/take_front.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::take_front` and `boost::hana::take_front_c`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/take_while.hpp b/boost/hana/take_while.hpp
index cda4816294..392459dca7 100644
--- a/boost/hana/take_while.hpp
+++ b/boost/hana/take_while.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::take_while`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/tap.hpp b/boost/hana/tap.hpp
index 37f757e7cc..7d37318255 100644
--- a/boost/hana/tap.hpp
+++ b/boost/hana/tap.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::tap`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/then.hpp b/boost/hana/then.hpp
index 9ee05ced0f..b6d74cfcf4 100644
--- a/boost/hana/then.hpp
+++ b/boost/hana/then.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::then`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/traits.hpp b/boost/hana/traits.hpp
index 2f599d78ab..983bdf8367 100644
--- a/boost/hana/traits.hpp
+++ b/boost/hana/traits.hpp
@@ -3,7 +3,7 @@
Defines function-like equivalents to the standard `<type_traits>`, and also
to some utilities like `std::declval`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/transform.hpp b/boost/hana/transform.hpp
index 7ecba83602..7c68731e2d 100644
--- a/boost/hana/transform.hpp
+++ b/boost/hana/transform.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::transform`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/tuple.hpp b/boost/hana/tuple.hpp
index 7273a6c2e0..cab5eaa4d6 100644
--- a/boost/hana/tuple.hpp
+++ b/boost/hana/tuple.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::tuple`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -44,12 +44,30 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename Xs, typename Ys, std::size_t ...n>
constexpr void assign(Xs& xs, Ys&& ys, std::index_sequence<n...>) {
int sequence[] = {int{}, ((void)(
- hana::get_impl<n>(xs) = hana::get_impl<n>(static_cast<Ys&&>(ys))
+ hana::at_c<n>(xs) = hana::at_c<n>(static_cast<Ys&&>(ys))
), int{})...};
(void)sequence;
}
struct from_index_sequence_t { };
+
+ template <typename Tuple, typename ...Yn>
+ struct is_same_tuple : std::false_type { };
+
+ template <typename Tuple>
+ struct is_same_tuple<typename detail::decay<Tuple>::type, Tuple>
+ : std::true_type
+ { };
+
+ template <bool SameTuple, bool SameNumberOfElements, typename Tuple, typename ...Yn>
+ struct enable_tuple_variadic_ctor;
+
+ template <typename ...Xn, typename ...Yn>
+ struct enable_tuple_variadic_ctor<false, true, hana::tuple<Xn...>, Yn...>
+ : std::enable_if<
+ detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
+ >
+ { };
}
//////////////////////////////////////////////////////////////////////////
@@ -75,7 +93,7 @@ BOOST_HANA_NAMESPACE_BEGIN
private:
template <typename Other, std::size_t ...n>
explicit constexpr tuple(detail::from_index_sequence_t, std::index_sequence<n...>, Other&& other)
- : storage_(hana::get_impl<n>(static_cast<Other&&>(other))...)
+ : storage_(hana::at_c<n>(static_cast<Other&&>(other))...)
{ }
public:
@@ -93,8 +111,9 @@ BOOST_HANA_NAMESPACE_BEGIN
: storage_(xn...)
{ }
- template <typename ...Yn, typename = typename std::enable_if<
- detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
+ template <typename ...Yn, typename = typename detail::enable_tuple_variadic_ctor<
+ detail::is_same_tuple<tuple, Yn...>::value,
+ sizeof...(Xn) == sizeof...(Yn), tuple, Yn...
>::type>
constexpr tuple(Yn&& ...yn)
: storage_(static_cast<Yn&&>(yn)...)
@@ -221,7 +240,7 @@ BOOST_HANA_NAMESPACE_BEGIN
template <typename Xs, typename N>
static constexpr decltype(auto) apply(Xs&& xs, N const&) {
constexpr std::size_t index = N::value;
- return hana::get_impl<index>(static_cast<Xs&&>(xs).storage_);
+ return hana::at_c<index>(static_cast<Xs&&>(xs).storage_);
}
};
@@ -251,17 +270,17 @@ BOOST_HANA_NAMESPACE_BEGIN
// compile-time optimizations (to reduce the # of function instantiations)
template <std::size_t n, typename ...Xs>
constexpr decltype(auto) at_c(tuple<Xs...> const& xs) {
- return hana::get_impl<n>(xs.storage_);
+ return hana::at_c<n>(xs.storage_);
}
template <std::size_t n, typename ...Xs>
constexpr decltype(auto) at_c(tuple<Xs...>& xs) {
- return hana::get_impl<n>(xs.storage_);
+ return hana::at_c<n>(xs.storage_);
}
template <std::size_t n, typename ...Xs>
constexpr decltype(auto) at_c(tuple<Xs...>&& xs) {
- return hana::get_impl<n>(static_cast<tuple<Xs...>&&>(xs).storage_);
+ return hana::at_c<n>(static_cast<tuple<Xs...>&&>(xs).storage_);
}
//////////////////////////////////////////////////////////////////////////
diff --git a/boost/hana/type.hpp b/boost/hana/type.hpp
index 853c843fb1..80a498753f 100644
--- a/boost/hana/type.hpp
+++ b/boost/hana/type.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::type` and related utilities.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/unfold_left.hpp b/boost/hana/unfold_left.hpp
index fff29f77ca..d058ac06b2 100644
--- a/boost/hana/unfold_left.hpp
+++ b/boost/hana/unfold_left.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::unfold_left`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/unfold_right.hpp b/boost/hana/unfold_right.hpp
index c0f4457c53..f9917bd7e1 100644
--- a/boost/hana/unfold_right.hpp
+++ b/boost/hana/unfold_right.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::unfold_right`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/union.hpp b/boost/hana/union.hpp
index 733f7b6bcd..d7bb4403bf 100644
--- a/boost/hana/union.hpp
+++ b/boost/hana/union.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::union`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/unique.hpp b/boost/hana/unique.hpp
index c4f30798eb..9485c332f0 100644
--- a/boost/hana/unique.hpp
+++ b/boost/hana/unique.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::unique`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/unpack.hpp b/boost/hana/unpack.hpp
index 03a4faed93..485821ea7a 100644
--- a/boost/hana/unpack.hpp
+++ b/boost/hana/unpack.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::unpack`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/value.hpp b/boost/hana/value.hpp
index fd5b5c4029..52d0581853 100644
--- a/boost/hana/value.hpp
+++ b/boost/hana/value.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::value`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/version.hpp b/boost/hana/version.hpp
index 33b30eddfc..2699bfd0e5 100644
--- a/boost/hana/version.hpp
+++ b/boost/hana/version.hpp
@@ -2,7 +2,7 @@
@file
Defines macros for tracking the version of the library.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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,11 +24,11 @@ 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 0
+#define BOOST_HANA_MINOR_VERSION 1
//! @ingroup group-config
//! Macro expanding to the patch level of the library, i.e. the `z` in `x.y.z`.
-#define BOOST_HANA_PATCH_VERSION 2
+#define BOOST_HANA_PATCH_VERSION 0
//! @ingroup group-config
//! Macro expanding to the full version of the library, in hexadecimal
diff --git a/boost/hana/while.hpp b/boost/hana/while.hpp
index 36ff9ab64b..312494daf5 100644
--- a/boost/hana/while.hpp
+++ b/boost/hana/while.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::while_`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/zero.hpp b/boost/hana/zero.hpp
index 6c71c9247d..baba9691f6 100644
--- a/boost/hana/zero.hpp
+++ b/boost/hana/zero.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::zero`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/zip.hpp b/boost/hana/zip.hpp
index d777701ad9..d18f3ef5e7 100644
--- a/boost/hana/zip.hpp
+++ b/boost/hana/zip.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::zip`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/zip_shortest.hpp b/boost/hana/zip_shortest.hpp
index 4976d79f42..761ca188c5 100644
--- a/boost/hana/zip_shortest.hpp
+++ b/boost/hana/zip_shortest.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::zip_shortest`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/hana/zip_shortest_with.hpp b/boost/hana/zip_shortest_with.hpp
index c0e6dcdf65..fc43f35239 100644
--- a/boost/hana/zip_shortest_with.hpp
+++ b/boost/hana/zip_shortest_with.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::zip_shortest_with`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
@@ -52,9 +52,10 @@ BOOST_HANA_NAMESPACE_BEGIN
constexpr std::size_t lengths[] = {
decltype(hana::length(xs))::value...
};
- constexpr std::size_t min = *detail::min_element(lengths, lengths + sizeof...(xs));
+ constexpr std::size_t min_len =
+ *detail::min_element(lengths, lengths + sizeof...(xs));
return hana::zip_with(static_cast<F&&>(f),
- hana::take_front(static_cast<Xs&&>(xs), hana::size_c<min>)...
+ hana::take_front(static_cast<Xs&&>(xs), hana::size_c<min_len>)...
);
}
};
diff --git a/boost/hana/zip_with.hpp b/boost/hana/zip_with.hpp
index 821b97d5db..8a5e153fe0 100644
--- a/boost/hana/zip_with.hpp
+++ b/boost/hana/zip_with.hpp
@@ -2,7 +2,7 @@
@file
Defines `boost::hana::zip_with`.
-@copyright Louis Dionne 2013-2016
+@copyright Louis Dionne 2013-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)
*/
diff --git a/boost/interprocess/detail/os_file_functions.hpp b/boost/interprocess/detail/os_file_functions.hpp
index bcb9576a19..7a41868188 100644
--- a/boost/interprocess/detail/os_file_functions.hpp
+++ b/boost/interprocess/detail/os_file_functions.hpp
@@ -102,6 +102,9 @@ inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
inline bool create_directory(const char *path)
{ return winapi::create_directory(path); }
+inline bool remove_directory(const char *path)
+{ return winapi::remove_directory(path); }
+
inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len)
{
required_len = 0;
@@ -422,6 +425,9 @@ inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
inline bool create_directory(const char *path)
{ return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; }
+inline bool remove_directory(const char *path)
+{ return ::rmdir(path) == 0; }
+
inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len)
{
required_len = 5u;
diff --git a/boost/interprocess/detail/os_thread_functions.hpp b/boost/interprocess/detail/os_thread_functions.hpp
index 3ff0a402ba..8a0a47cc27 100644
--- a/boost/interprocess/detail/os_thread_functions.hpp
+++ b/boost/interprocess/detail/os_thread_functions.hpp
@@ -53,7 +53,12 @@
# include <sys/sysctl.h>
# endif
//According to the article "C/C++ tip: How to measure elapsed real time for benchmarking"
-# if defined(CLOCK_MONOTONIC_PRECISE) //BSD
+//Check MacOs first as macOS 10.12 SDK defines both CLOCK_MONOTONIC and
+//CLOCK_MONOTONIC_RAW and no clock_gettime.
+# if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
+# include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
+# define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
+# elif defined(CLOCK_MONOTONIC_PRECISE) //BSD
# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE
# elif defined(CLOCK_MONOTONIC_RAW) //Linux
# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
@@ -61,9 +66,6 @@
# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_HIGHRES
# elif defined(CLOCK_MONOTONIC) //POSIX (AIX, BSD, Linux, Solaris)
# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC
-# elif !defined(CLOCK_MONOTONIC) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
-# include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
-# define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
# else
# error "No high resolution steady clock in your system, please provide a patch"
# endif
@@ -112,8 +114,8 @@ inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
//return the system tick in ns
inline unsigned long get_system_tick_ns()
{
- unsigned long curres;
- winapi::set_timer_resolution(10000, 0, &curres);
+ unsigned long curres, ignore1, ignore2;
+ winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
//Windows API returns the value in hundreds of ns
return (curres - 1ul)*100ul;
}
@@ -121,8 +123,8 @@ inline unsigned long get_system_tick_ns()
//return the system tick in us
inline unsigned long get_system_tick_us()
{
- unsigned long curres;
- winapi::set_timer_resolution(10000, 0, &curres);
+ unsigned long curres, ignore1, ignore2;
+ winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
//Windows API returns the value in hundreds of ns
return (curres - 1ul)/10ul + 1ul;
}
@@ -132,8 +134,8 @@ typedef unsigned __int64 OS_highres_count_t;
inline unsigned long get_system_tick_in_highres_counts()
{
__int64 freq;
- unsigned long curres;
- winapi::set_timer_resolution(10000, 0, &curres);
+ unsigned long curres, ignore1, ignore2;
+ winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
//Frequency in counts per second
if(!winapi::query_performance_frequency(&freq)){
//Tick resolution in ms
diff --git a/boost/interprocess/detail/shared_dir_helpers.hpp b/boost/interprocess/detail/shared_dir_helpers.hpp
index 5d4d1b3842..0fcd898dcb 100755
--- a/boost/interprocess/detail/shared_dir_helpers.hpp
+++ b/boost/interprocess/detail/shared_dir_helpers.hpp
@@ -124,15 +124,11 @@ inline void get_shared_dir_root(std::string &dir_path)
#endif
#ifdef BOOST_INTERPROCESS_SHARED_DIR_FUNC
-namespace boost {
- namespace interprocess {
- namespace ipcdetail {
- // When BOOST_INTERPROCESS_SHARED_DIR_FUNC is defined, users have to implement
- // get_shared_dir
- void get_shared_dir(std::string &shared_dir);
- }
- }
-}
+
+ // When BOOST_INTERPROCESS_SHARED_DIR_FUNC is defined, users have to implement
+ // get_shared_dir
+ void get_shared_dir(std::string &shared_dir);
+
#else
inline void get_shared_dir(std::string &shared_dir)
{
diff --git a/boost/interprocess/detail/utilities.hpp b/boost/interprocess/detail/utilities.hpp
index e1be2f1598..c1b23423c2 100644
--- a/boost/interprocess/detail/utilities.hpp
+++ b/boost/interprocess/detail/utilities.hpp
@@ -156,29 +156,29 @@ BOOST_INTERPROCESS_FORCEINLINE bool size_overflows(SizeType count)
return multiplication_overflows(SizeType(SztSizeOfType), count);
}
-template<class RawPointer>
-class pointer_uintptr_caster;
+template<class RawPointer, class OffsetType>
+class pointer_offset_caster;
-template<class T>
-class pointer_uintptr_caster<T*>
+template<class T, class OffsetType>
+class pointer_offset_caster<T*, OffsetType>
{
public:
- BOOST_INTERPROCESS_FORCEINLINE explicit pointer_uintptr_caster(uintptr_t sz)
- : m_uintptr(sz)
+ BOOST_INTERPROCESS_FORCEINLINE explicit pointer_offset_caster(OffsetType offset)
+ : m_offset(offset)
{}
- BOOST_INTERPROCESS_FORCEINLINE explicit pointer_uintptr_caster(const volatile T *p)
- : m_uintptr(reinterpret_cast<uintptr_t>(p))
+ BOOST_INTERPROCESS_FORCEINLINE explicit pointer_offset_caster(const volatile T *p)
+ : m_offset(reinterpret_cast<OffsetType>(p))
{}
- BOOST_INTERPROCESS_FORCEINLINE uintptr_t uintptr() const
- { return m_uintptr; }
+ BOOST_INTERPROCESS_FORCEINLINE OffsetType offset() const
+ { return m_offset; }
BOOST_INTERPROCESS_FORCEINLINE T* pointer() const
- { return reinterpret_cast<T*>(m_uintptr); }
+ { return reinterpret_cast<T*>(m_offset); }
private:
- uintptr_t m_uintptr;
+ OffsetType m_offset;
};
diff --git a/boost/interprocess/detail/win32_api.hpp b/boost/interprocess/detail/win32_api.hpp
index 02c7b42706..1ea8cec53d 100644
--- a/boost/interprocess/detail/win32_api.hpp
+++ b/boost/interprocess/detail/win32_api.hpp
@@ -31,9 +31,45 @@
#include <string>
#include <vector>
+//#define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME
+//#define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED
+//#define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED
+
+#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME
+# define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME_VALUE 1
+#else
+# define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME_VALUE 0
+#endif
+
+#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED
+# define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED_VALUE 1
+#else
+# define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED_VALUE 0
+#endif
+
+#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED
+# define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED_VALUE 1
+#else
+# define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED_VALUE 0
+#endif
+
+#define BOOST_INTERPROCESS_BOOTSTAMP_VALUE_SUM \
+ (BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED_VALUE + \
+ BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED_VALUE + \
+ BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME_VALUE)
+
+#if 1 < BOOST_INTERPROCESS_BOOTSTAMP_VALUE_SUM
+# error "Only one of BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME, \
+ BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED and \
+ BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED can be defined"
+#endif
+
+#if 0 == BOOST_INTERPROCESS_BOOTSTAMP_VALUE_SUM
+# define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED
+#endif
+
#ifdef BOOST_USE_WINDOWS_H
#include <windows.h>
-
# if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME)
# include <wbemidl.h>
# include <objbase.h>
@@ -1162,6 +1198,23 @@ const unsigned long COINIT_MULTITHREADED_BIPC = 0x0;
const unsigned long COINIT_DISABLE_OLE1DDE_BIPC = 0x4;
const unsigned long COINIT_SPEED_OVER_MEMORY_BIPC = 0x4;
+// Registry types
+#define reg_none ( 0 ) // No value type
+#define reg_sz ( 1 ) // Unicode nul terminated string
+#define reg_expand_sz ( 2 ) // Unicode nul terminated string
+ // (with environment variable references)
+#define reg_binary ( 3 ) // Free form binary
+#define reg_dword ( 4 ) // 32-bit number
+#define reg_dword_little_endian ( 4 ) // 32-bit number (same as REG_DWORD)
+#define reg_dword_big_endian ( 5 ) // 32-bit number
+#define reg_link ( 6 ) // Symbolic Link (unicode)
+#define reg_multi_sz ( 7 ) // Multiple Unicode strings
+#define reg_resource_list ( 8 ) // Resource list in the resource map
+#define reg_full_resource_descriptor ( 9 ) // Resource list in the hardware description
+#define reg_resource_requirements_list ( 10 )
+#define reg_qword ( 11 ) // 64-bit number
+#define reg_qword_little_endian ( 11 ) // 64-bit number (same as reg_qword)
+
//If the user needs to change default COM initialization model,
//it can define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL to one of these:
@@ -1654,28 +1707,6 @@ inline bool get_boot_and_system_time(unsigned char (&bootsystemstamp) [BootAndSy
return true;
}
-inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s)
- //will write BootstampLength chars
-{
- if(s < (BootstampLength*2))
- return false;
- system_timeofday_information info;
- bool ret = get_system_time_of_day_information(info);
- if(!ret){
- return false;
- }
- const char Characters [] =
- { '0', '1', '2', '3', '4', '5', '6', '7'
- , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
- std::size_t char_counter = 0;
- for(std::size_t i = 0; i != static_cast<std::size_t>(BootstampLength); ++i){
- bootstamp_str[char_counter++] = Characters[(info.Reserved1[i]&0xF0)>>4];
- bootstamp_str[char_counter++] = Characters[(info.Reserved1[i]&0x0F)];
- }
- s = BootstampLength*2;
- return true;
-}
-
//Writes the hexadecimal value of the buffer, in the wide character string.
//str must be twice length
inline void buffer_to_wide_str(const void *buf, std::size_t length, wchar_t *str)
@@ -1691,6 +1722,37 @@ inline void buffer_to_wide_str(const void *buf, std::size_t length, wchar_t *str
}
}
+//Writes the hexadecimal value of the buffer, in the narrow character string.
+//str must be twice length
+inline void buffer_to_narrow_str(const void *buf, std::size_t length, char *str)
+{
+ const char Characters [] =
+ { '0', '1', '2', '3', '4', '5', '6', '7'
+ , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ std::size_t char_counter = 0;
+ const char *chbuf = static_cast<const char *>(buf);
+ for(std::size_t i = 0; i != length; ++i){
+ str[char_counter++] = Characters[(chbuf[i]&0xF0)>>4];
+ str[char_counter++] = Characters[(chbuf[i]&0x0F)];
+ }
+}
+
+inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s)
+ //will write BootstampLength chars
+{
+ if(s < (BootstampLength*2))
+ return false;
+ system_timeofday_information info;
+ bool ret = get_system_time_of_day_information(info);
+ if(!ret){
+ return false;
+ }
+
+ buffer_to_narrow_str(info.Reserved1, BootstampLength, bootstamp_str);
+ s = BootstampLength*2;
+ return true;
+}
+
inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t &s)
//will write BootAndSystemstampLength chars
{
@@ -1748,7 +1810,7 @@ class nt_query_mem_deleter
(SystemTimeOfDayInfoLength + sizeof(unsigned long) + sizeof(boost::uint32_t))*2;
public:
- nt_query_mem_deleter(std::size_t object_name_information_size)
+ explicit nt_query_mem_deleter(std::size_t object_name_information_size)
: m_size(object_name_information_size + rename_offset + rename_suffix)
, m_buf(new char [m_size])
{}
@@ -1786,7 +1848,7 @@ class nt_query_mem_deleter
class c_heap_deleter
{
public:
- c_heap_deleter(std::size_t size)
+ explicit c_heap_deleter(std::size_t size)
: m_buf(::malloc(size))
{}
@@ -1935,13 +1997,35 @@ struct reg_closer
~reg_closer(){ reg_close_key(key_); }
};
-inline void get_shared_documents_folder(std::string &s)
+inline bool get_registry_value_buffer(hkey key_type, const char *subkey_name, const char *value_name, void *buf, std::size_t &buflen)
{
- #if 1 //Original registry search code
+ bool bret = false;
+ hkey key;
+ if (reg_open_key_ex( key_type
+ , subkey_name
+ , 0
+ , key_query_value
+ , &key) == 0){
+ reg_closer key_closer(key);
+
+ //Obtain the value
+ unsigned long size = buflen;
+ unsigned long type;
+ buflen = 0;
+ bret = 0 == reg_query_value_ex( key, value_name, 0, &type, (unsigned char*)buf, &size);
+ if(bret)
+ buflen = (std::size_t)size;
+ }
+ return bret;
+}
+
+inline bool get_registry_value_string(hkey key_type, const char *subkey_name, const char *value_name, std::string &s)
+{
+ bool bret = false;
s.clear();
hkey key;
- if (reg_open_key_ex( hkey_local_machine
- , "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
+ if (reg_open_key_ex( key_type
+ , subkey_name
, 0
, key_query_value
, &key) == 0){
@@ -1950,19 +2034,28 @@ inline void get_shared_documents_folder(std::string &s)
//Obtain the value
unsigned long size;
unsigned long type;
- const char *const reg_value = "Common AppData";
- //long err = (*pRegQueryValue)( key, reg_value, 0, &type, 0, &size);
- long err = reg_query_value_ex( key, reg_value, 0, &type, 0, &size);
- if(!err){
+ long err = reg_query_value_ex( key, value_name, 0, &type, 0, &size);
+ if((reg_sz == type || reg_expand_sz != type) && !err){
//Size includes terminating NULL
s.resize(size);
- //err = (*pRegQueryValue)( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size);
- err = reg_query_value_ex( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size);
- if(!err)
+ err = reg_query_value_ex( key, value_name, 0, &type, (unsigned char*)(&s[0]), &size);
+ if(!err){
s.erase(s.end()-1);
+ bret = true;
+ }
(void)err;
}
}
+ return bret;
+}
+
+inline void get_shared_documents_folder(std::string &s)
+{
+ #if 1 //Original registry search code
+ get_registry_value_string( hkey_local_machine
+ , "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
+ , "Common AppData"
+ , s);
#else //registry alternative: SHGetFolderPath
const int BIPC_CSIDL_COMMON_APPDATA = 0x0023; // All Users\Application Data
const int BIPC_CSIDL_FLAG_CREATE = 0x8000; // new for Win2K, or this in to force creation of folder
@@ -2175,7 +2268,9 @@ inline bool get_last_bootup_time( std::string& str )
return ret;
}
-#else
+#endif //BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME
+
+#if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED)
// Loop through the buffer and obtain the contents of the
// requested record in the buffer.
@@ -2271,7 +2366,41 @@ inline bool get_last_bootup_time(std::string &stamp)
return true;
}
-#endif
+#endif //BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED
+
+#if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED)
+
+inline bool get_last_bootup_time(std::string &stamp)
+{
+ unsigned dword_val = 0;
+ std::size_t dword_size = sizeof(dword_val);
+ bool b_ret = get_registry_value_buffer( hkey_local_machine
+ , "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters"
+ , "BootId", &dword_val, dword_size);
+ if (b_ret)
+ {
+ char dword_str[sizeof(dword_val)*2u+1];
+ buffer_to_narrow_str(&dword_val, dword_size, dword_str);
+ dword_str[sizeof(dword_val)*2] = '\0';
+ stamp = dword_str;
+
+ b_ret = get_registry_value_buffer( hkey_local_machine
+ , "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power"
+ , "HybridBootAnimationTime", &dword_val, dword_size);
+ //Old Windows versions have no HybridBootAnimationTime
+ if(b_ret)
+ {
+ buffer_to_narrow_str(&dword_val, dword_size, dword_str);
+ dword_str[sizeof(dword_val)*2] = '\0';
+ stamp += "_";
+ stamp += dword_str;
+ }
+ b_ret = true;
+ }
+ return b_ret;
+}
+
+#endif //BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED
inline bool is_directory(const char *path)
{
diff --git a/boost/interprocess/offset_ptr.hpp b/boost/interprocess/offset_ptr.hpp
index fca444eaa4..24b044adf4 100644
--- a/boost/interprocess/offset_ptr.hpp
+++ b/boost/interprocess/offset_ptr.hpp
@@ -23,6 +23,9 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_constructible.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_unsigned.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/detail/utilities.hpp>
@@ -55,6 +58,7 @@ namespace ipcdetail {
union offset_ptr_internal
{
BOOST_STATIC_ASSERT(sizeof(OffsetType) >= sizeof(uintptr_t));
+ BOOST_STATIC_ASSERT(boost::is_integral<OffsetType>::value && boost::is_unsigned<OffsetType>::value);
explicit offset_ptr_internal(OffsetType off)
: m_offset(off)
@@ -81,20 +85,21 @@ namespace ipcdetail {
//
////////////////////////////////////////////////////////////////////////
#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
- BOOST_INTERPROCESS_FORCEINLINE void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, uintptr_t offset)
+ template <class OffsetType>
+ BOOST_INTERPROCESS_FORCEINLINE void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, OffsetType offset)
{
- typedef pointer_uintptr_caster<void*> caster_t;
+ typedef pointer_offset_caster<void*, OffsetType> caster_t;
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
if(offset == 1){
return 0;
}
else{
- return caster_t(caster_t(this_ptr).uintptr() + offset).pointer();
+ return caster_t(caster_t(this_ptr).offset() + offset).pointer();
}
#else
- uintptr_t mask = offset == 1;
+ OffsetType mask = offset == 1;
--mask;
- uintptr_t target_offset = caster_t(this_ptr).uintptr() + offset;
+ OffsetType target_offset = caster_t(this_ptr).offset() + offset;
target_offset &= mask;
return caster_t(target_offset).pointer();
#endif
@@ -106,27 +111,28 @@ namespace ipcdetail {
//
////////////////////////////////////////////////////////////////////////
#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
- BOOST_INTERPROCESS_FORCEINLINE uintptr_t offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr)
+ template<class OffsetType>
+ BOOST_INTERPROCESS_FORCEINLINE OffsetType offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr)
{
- typedef pointer_uintptr_caster<void*> caster_t;
+ typedef pointer_offset_caster<void*, OffsetType> caster_t;
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
//offset == 1 && ptr != 0 is not legal for this pointer
if(!ptr){
return 1;
}
else{
- uintptr_t offset = caster_t(ptr).uintptr() - caster_t(this_ptr).uintptr();
+ OffsetType offset = caster_t(ptr).offset()- caster_t(this_ptr).offset();
BOOST_ASSERT(offset != 1);
return offset;
}
#else
- //const uintptr_t other = -uintptr_t(ptr != 0);
- //const uintptr_t offset = (caster_t(ptr).uintptr() - caster_t(this_ptr).uintptr()) & other;
- //return offset + uintptr_t(!other);
+ //const OffsetType other = -OffsetType(ptr != 0);
+ //const OffsetType offset = (caster_t(ptr).offset() - caster_t(this_ptr).offset()) & other;
+ //return offset + OffsetType(!other);
//
- uintptr_t offset = caster_t(ptr).uintptr() - caster_t(this_ptr).uintptr();
+ OffsetType offset = caster_t(ptr).offset() - caster_t(this_ptr).offset();
--offset;
- uintptr_t mask = uintptr_t(ptr == 0);
+ OffsetType mask = ptr == 0;
--mask;
offset &= mask;
return ++offset;
@@ -139,28 +145,29 @@ namespace ipcdetail {
//
////////////////////////////////////////////////////////////////////////
#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
- BOOST_INTERPROCESS_FORCEINLINE uintptr_t offset_ptr_to_offset_from_other
- (const volatile void *this_ptr, const volatile void *other_ptr, uintptr_t other_offset)
+ template<class OffsetType>
+ BOOST_INTERPROCESS_FORCEINLINE OffsetType offset_ptr_to_offset_from_other
+ (const volatile void *this_ptr, const volatile void *other_ptr, OffsetType other_offset)
{
- typedef pointer_uintptr_caster<void*> caster_t;
+ typedef pointer_offset_caster<void*, OffsetType> caster_t;
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
if(other_offset == 1){
return 1;
}
else{
- uintptr_t offset = caster_t(other_ptr).uintptr() - caster_t(this_ptr).uintptr() + other_offset;
+ OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset() + other_offset;
BOOST_ASSERT(offset != 1);
return offset;
}
#else
- uintptr_t mask = other_offset == 1;
+ OffsetType mask = other_offset == 1;
--mask;
- uintptr_t offset = caster_t(other_ptr).uintptr() - caster_t(this_ptr).uintptr();
+ OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset();
offset &= mask;
return offset + other_offset;
- //uintptr_t mask = -uintptr_t(other_offset != 1);
- //uintptr_t offset = caster_t(other_ptr).uintptr() - caster_t(this_ptr).uintptr();
+ //OffsetType mask = -OffsetType(other_offset != 1);
+ //OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset();
//offset &= mask;
//return offset + other_offset;
#endif
@@ -215,9 +222,9 @@ namespace ipcdetail {
//!
//!<b>Note</b>: offset_ptr uses implementation defined properties, present in most platforms, for
//!performance reasons:
-//! - Assumes that uintptr_t representation of nullptr is (uintptr_t)zero.
-//! - Assumes that incrementing a uintptr_t obtained from a pointer is equivalent
-//! to incrementing the pointer and then converting it back to uintptr_t.
+//! - Assumes that OffsetType representation of nullptr is (OffsetType)zero.
+//! - Assumes that incrementing a OffsetType obtained from a pointer is equivalent
+//! to incrementing the pointer and then converting it back to OffsetType.
template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
class offset_ptr
{
@@ -251,7 +258,7 @@ class offset_ptr
//!Constructor from raw pointer (allows "0" pointer conversion).
//!Never throws.
BOOST_INTERPROCESS_FORCEINLINE offset_ptr(pointer ptr) BOOST_NOEXCEPT
- : internal(static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset(ptr, this)))
+ : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(ptr, this))
{}
//!Constructor from other pointer.
@@ -259,78 +266,81 @@ class offset_ptr
template <class T>
BOOST_INTERPROCESS_FORCEINLINE offset_ptr( T *ptr
, typename ipcdetail::enable_if< ::boost::is_convertible<T*, PointedType*> >::type * = 0) BOOST_NOEXCEPT
- : internal(static_cast<OffsetType>
- (ipcdetail::offset_ptr_to_offset(static_cast<PointedType*>(ptr), this)))
+ : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(static_cast<PointedType*>(ptr), this))
{}
//!Constructor from other offset_ptr
//!Never throws.
BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr& ptr) BOOST_NOEXCEPT
- : internal(static_cast<OffsetType>
- (ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset)))
+ : internal(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset))
{}
- //!Constructor from other offset_ptr. If pointers of pointee types are
- //!convertible, offset_ptrs will be convertibles. Never throws.
+ //!Constructor from other offset_ptr. Only takes part in overload resolution
+ //!if T2* is convertible to PointedType*. Never throws.
template<class T2>
BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
, typename ipcdetail::enable_if_convertible_equal_address<T2, PointedType>::type* = 0
#endif
) BOOST_NOEXCEPT
- : internal(static_cast<OffsetType>
- (ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset())))
+ : internal(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset()))
{}
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
- //!Constructor from other offset_ptr. If pointers of pointee types are
- //!convertible, offset_ptrs will be convertibles. Never throws.
template<class T2>
BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
, typename ipcdetail::enable_if_convertible_unequal_address<T2, PointedType>::type* = 0) BOOST_NOEXCEPT
- : internal(static_cast<OffsetType>
- (ipcdetail::offset_ptr_to_offset(static_cast<PointedType*>(ptr.get()), this)))
+ : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(static_cast<PointedType*>(ptr.get()), this))
{}
#endif
+ //!Constructor from other offset_ptr. Only takes part in overload resolution
+ //!if PointedType* is constructible from T2* other than via a conversion (e.g. cast to a derived class). Never throws.
+ template<class T2>
+ BOOST_INTERPROCESS_FORCEINLINE explicit offset_ptr(const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
+ #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ , typename ipcdetail::enable_if_c<
+ !::boost::is_convertible<T2*, PointedType*>::value && ::boost::is_constructible<T2*, PointedType*>::value
+ >::type * = 0
+ #endif
+ ) BOOST_NOEXCEPT
+ : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(static_cast<PointedType*>(ptr.get()), this))
+ {}
+
//!Emulates static_cast operator.
//!Never throws.
template<class T2, class P2, class O2, std::size_t A2>
BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::static_cast_tag) BOOST_NOEXCEPT
- : internal(static_cast<OffsetType>
- (ipcdetail::offset_ptr_to_offset(static_cast<PointedType*>(r.get()), this)))
+ : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(static_cast<PointedType*>(r.get()), this))
{}
//!Emulates const_cast operator.
//!Never throws.
template<class T2, class P2, class O2, std::size_t A2>
BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::const_cast_tag) BOOST_NOEXCEPT
- : internal(static_cast<OffsetType>
- (ipcdetail::offset_ptr_to_offset(const_cast<PointedType*>(r.get()), this)))
+ : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(const_cast<PointedType*>(r.get()), this))
{}
//!Emulates dynamic_cast operator.
//!Never throws.
template<class T2, class P2, class O2, std::size_t A2>
BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::dynamic_cast_tag) BOOST_NOEXCEPT
- : internal(static_cast<OffsetType>
- (ipcdetail::offset_ptr_to_offset(dynamic_cast<PointedType*>(r.get()), this)))
+ : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(dynamic_cast<PointedType*>(r.get()), this))
{}
//!Emulates reinterpret_cast operator.
//!Never throws.
template<class T2, class P2, class O2, std::size_t A2>
BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::reinterpret_cast_tag) BOOST_NOEXCEPT
- : internal(static_cast<OffsetType>
- (ipcdetail::offset_ptr_to_offset(reinterpret_cast<PointedType*>(r.get()), this)))
+ : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(reinterpret_cast<PointedType*>(r.get()), this))
{}
//!Obtains raw pointer from offset.
//!Never throws.
BOOST_INTERPROCESS_FORCEINLINE pointer get() const BOOST_NOEXCEPT
- { return (pointer)ipcdetail::offset_ptr_to_raw_pointer(this, this->internal.m_offset); }
+ { return static_cast<pointer>(ipcdetail::offset_ptr_to_raw_pointer(this, this->internal.m_offset)); }
BOOST_INTERPROCESS_FORCEINLINE offset_type get_offset() const BOOST_NOEXCEPT
{ return this->internal.m_offset; }
@@ -358,8 +368,7 @@ class offset_ptr
//!Never throws.
BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (pointer from) BOOST_NOEXCEPT
{
- this->internal.m_offset =
- static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset(from, this));
+ this->internal.m_offset = ipcdetail::offset_ptr_to_offset<OffsetType>(from, this);
return *this;
}
@@ -367,8 +376,7 @@ class offset_ptr
//!Never throws.
BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (const offset_ptr & ptr) BOOST_NOEXCEPT
{
- this->internal.m_offset =
- static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset));
+ this->internal.m_offset = ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset);
return *this;
}
@@ -444,9 +452,17 @@ class offset_ptr
//!Compatibility with pointer_traits
//!
+ #if defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class U>
struct rebind
{ typedef offset_ptr<U, DifferenceType, OffsetType, OffsetAlignment> other; };
+ #else
+ template <class U>
+ using rebind = offset_ptr<U, DifferenceType, OffsetType, OffsetAlignment>;
+ #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ typedef offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> other;
+ #endif //BOOST_INTERPROCESS_DOXYGEN_INVOKED
+ #endif
//!Compatibility with pointer_traits
//!
@@ -546,15 +562,13 @@ class offset_ptr
template<class T2>
BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr, ipcdetail::bool_<true>) BOOST_NOEXCEPT
{ //no need to pointer adjustment
- this->internal.m_offset =
- static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset()));
+ this->internal.m_offset = ipcdetail::offset_ptr_to_offset_from_other<OffsetType>(this, &ptr, ptr.get_offset());
}
template<class T2>
BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr, ipcdetail::bool_<false>) BOOST_NOEXCEPT
{ //we must convert to raw before calculating the offset
- this->internal.m_offset =
- static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset(static_cast<PointedType*>(ptr.get()), this));
+ this->internal.m_offset = ipcdetail::offset_ptr_to_offset<OffsetType>(static_cast<PointedType*>(ptr.get()), this);
}
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
@@ -692,7 +706,7 @@ struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits>
typedef boost::interprocess::offset_ptr<T, P, O, A> pointer;
//Bits are stored in the lower bits of the pointer except the LSB,
//because this bit is used to represent the null pointer.
- static const uintptr_t Mask = ((uintptr_t(1) << uintptr_t(NumBits)) - uintptr_t(1)) << uintptr_t(1);
+ static const O Mask = ((static_cast<O>(1) << NumBits) - static_cast<O>(1)) << 1;
BOOST_STATIC_ASSERT(0 ==(Mask&1));
//We must ALWAYS take argument "n" by reference as a copy of a null pointer
@@ -701,7 +715,7 @@ struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits>
BOOST_INTERPROCESS_FORCEINLINE static pointer get_pointer(const pointer &n) BOOST_NOEXCEPT
{
pointer p;
- O const tmp_off = n.priv_offset() & O(~Mask);
+ O const tmp_off = n.priv_offset() & ~Mask;
p.priv_offset() = boost::interprocess::ipcdetail::offset_ptr_to_offset_from_other(&p, &n, tmp_off);
return p;
}
@@ -709,7 +723,7 @@ struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits>
BOOST_INTERPROCESS_FORCEINLINE static void set_pointer(pointer &n, const pointer &p) BOOST_NOEXCEPT
{
BOOST_ASSERT(0 == (get_bits)(p));
- O const stored_bits = O(n.priv_offset() & Mask);
+ O const stored_bits = n.priv_offset() & Mask;
n = p;
n.priv_offset() |= stored_bits;
}
@@ -723,7 +737,7 @@ struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits>
{
BOOST_ASSERT(b < (std::size_t(1) << NumBits));
O tmp = n.priv_offset();
- tmp &= O(~Mask);
+ tmp &= ~Mask;
tmp |= O(b << 1u);
n.priv_offset() = tmp;
}
diff --git a/boost/intrusive/bstree.hpp b/boost/intrusive/bstree.hpp
index f2cdb428b4..1eeab55113 100644
--- a/boost/intrusive/bstree.hpp
+++ b/boost/intrusive/bstree.hpp
@@ -967,7 +967,7 @@ class bstree_impl
void swap(bstree_impl& other)
{
//This can throw
- ::boost::adl_move_swap(this->comp(), this->comp());
+ ::boost::adl_move_swap(this->comp(), other.comp());
//These can't throw
node_algorithms::swap_tree(this->header_ptr(), node_ptr(other.header_ptr()));
this->sz_traits().swap(other.sz_traits());
diff --git a/boost/intrusive/bstree_algorithms.hpp b/boost/intrusive/bstree_algorithms.hpp
index e8caee0c94..e449ebac08 100644
--- a/boost/intrusive/bstree_algorithms.hpp
+++ b/boost/intrusive/bstree_algorithms.hpp
@@ -37,6 +37,9 @@ namespace intrusive {
template <class NodePtr>
struct insert_commit_data_t
{
+ BOOST_INTRUSIVE_FORCEINLINE insert_commit_data_t()
+ : link_left(false), node()
+ {}
bool link_left;
NodePtr node;
};
diff --git a/boost/intrusive/detail/key_nodeptr_comp.hpp b/boost/intrusive/detail/key_nodeptr_comp.hpp
index 9d64f09bcd..bdc025e5ab 100644
--- a/boost/intrusive/detail/key_nodeptr_comp.hpp
+++ b/boost/intrusive/detail/key_nodeptr_comp.hpp
@@ -59,6 +59,10 @@ struct key_nodeptr_comp
//Use public inheritance to avoid MSVC bugs with closures
: public key_nodeptr_comp_types<KeyTypeKeyCompare, ValueTraits, KeyOfValue>::base_t
{
+private:
+ struct sfinae_type;
+
+public:
typedef key_nodeptr_comp_types<KeyTypeKeyCompare, ValueTraits, KeyOfValue> types_t;
typedef typename types_t::value_traits value_traits;
typedef typename types_t::value_type value_type;
@@ -83,32 +87,32 @@ struct key_nodeptr_comp
//pred(pnode)
template<class T1>
- BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value >::type* =0) const
+ BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value, sfinae_type* >::type = 0) const
{ return base().get()(key_of_value()(*traits_->to_value_ptr(t1))); }
//operator() 2 arg
//pred(pnode, pnode)
template<class T1, class T2>
BOOST_INTRUSIVE_FORCEINLINE bool operator()
- (const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value && is_same_or_nodeptr_convertible<T2>::value >::type* =0) const
+ (const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value && is_same_or_nodeptr_convertible<T2>::value, sfinae_type* >::type = 0) const
{ return base()(*traits_->to_value_ptr(t1), *traits_->to_value_ptr(t2)); }
//pred(pnode, key)
template<class T1, class T2>
BOOST_INTRUSIVE_FORCEINLINE bool operator()
- (const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value && !is_same_or_nodeptr_convertible<T2>::value >::type* =0) const
+ (const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value && !is_same_or_nodeptr_convertible<T2>::value, sfinae_type* >::type = 0) const
{ return base()(*traits_->to_value_ptr(t1), t2); }
//pred(key, pnode)
template<class T1, class T2>
BOOST_INTRUSIVE_FORCEINLINE bool operator()
- (const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible<T1>::value && is_same_or_nodeptr_convertible<T2>::value >::type* =0) const
+ (const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible<T1>::value && is_same_or_nodeptr_convertible<T2>::value, sfinae_type* >::type = 0) const
{ return base()(t1, *traits_->to_value_ptr(t2)); }
//pred(key, key)
template<class T1, class T2>
BOOST_INTRUSIVE_FORCEINLINE bool operator()
- (const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible<T1>::value && !is_same_or_nodeptr_convertible<T2>::value >::type* =0) const
+ (const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible<T1>::value && !is_same_or_nodeptr_convertible<T2>::value, sfinae_type* >::type = 0) const
{ return base()(t1, t2); }
const ValueTraits *const traits_;
diff --git a/boost/intrusive/slist.hpp b/boost/intrusive/slist.hpp
index 00206990f6..f34350d80f 100644
--- a/boost/intrusive/slist.hpp
+++ b/boost/intrusive/slist.hpp
@@ -1115,7 +1115,7 @@ class slist_impl
//!
//! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: Lineal to the elements (l - before_f + 1).
+ //! <b>Complexity</b>: Linear to the elements (l - before_f + 1).
//!
//! <b>Note</b>: Invalidates the iterators to the erased element.
template<class Disposer>
diff --git a/boost/intrusive/treap.hpp b/boost/intrusive/treap.hpp
index 8567072d54..c6f63ff2de 100644
--- a/boost/intrusive/treap.hpp
+++ b/boost/intrusive/treap.hpp
@@ -354,9 +354,9 @@ class treap_impl
//! <b>Throws</b>: If the comparison functor's swap call throws.
void swap(treap_impl& other)
{
- tree_type::swap(other);
//This can throw
::boost::adl_move_swap(this->priv_pcomp(), other.priv_pcomp());
+ tree_type::swap(other);
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
diff --git a/boost/iostreams/chain.hpp b/boost/iostreams/chain.hpp
index a199c9df38..4e108c8b09 100644
--- a/boost/iostreams/chain.hpp
+++ b/boost/iostreams/chain.hpp
@@ -14,10 +14,9 @@
#include <boost/assert.hpp>
#include <exception>
-#include <functional> // unary_function.
#include <iterator> // advance.
#include <list>
-#include <memory> // allocator, auto_ptr.
+#include <memory> // allocator, auto_ptr or unique_ptr.
#include <typeinfo>
#include <stdexcept> // logic_error, out_of_range.
#include <boost/checked_delete.hpp>
@@ -243,8 +242,19 @@ private:
pback_size != -1 ?
pback_size :
pimpl_->pback_size_;
+
+#if defined(BOOST_NO_CXX11_SMART_PTR)
+
std::auto_ptr<streambuf_t>
buf(new streambuf_t(t, buffer_size, pback_size));
+
+#else
+
+ std::unique_ptr<streambuf_t>
+ buf(new streambuf_t(t, buffer_size, pback_size));
+
+#endif
+
list().push_back(buf.get());
buf.release();
if (is_device<component_type>::value) {
@@ -281,7 +291,9 @@ private:
static void set_auto_close(streambuf_type* b, bool close)
{ b->set_auto_close(close); }
- struct closer : public std::unary_function<streambuf_type*, void> {
+ struct closer {
+ typedef streambuf_type* argument_type;
+ typedef void result_type;
closer(BOOST_IOS::openmode m) : mode_(m) { }
void operator() (streambuf_type* b)
{
@@ -472,7 +484,7 @@ public:
BOOST_IOSTREAMS_DEFINE_PUSH(push, mode, char_type, push_impl)
void pop() { chain_->pop(); }
bool empty() const { return chain_->empty(); }
- size_type size() { return chain_->size(); }
+ size_type size() const { return chain_->size(); }
void reset() { chain_->reset(); }
// Returns a copy of the underlying chain.
diff --git a/boost/iostreams/code_converter.hpp b/boost/iostreams/code_converter.hpp
index 85d5c80eeb..0bac461d44 100644
--- a/boost/iostreams/code_converter.hpp
+++ b/boost/iostreams/code_converter.hpp
@@ -37,7 +37,7 @@
#include <boost/iostreams/detail/execute.hpp>
#include <boost/iostreams/detail/forward.hpp>
#include <boost/iostreams/detail/functional.hpp>
-#include <boost/iostreams/detail/ios.hpp> // failure, openmode, int types.
+#include <boost/iostreams/detail/ios.hpp> // failure, openmode, int types, streamsize.
#include <boost/iostreams/detail/optional.hpp>
#include <boost/iostreams/detail/select.hpp>
#include <boost/iostreams/traits.hpp>
@@ -154,13 +154,13 @@ struct code_converter_impl {
}
template <class T>
- void open(const T& dev, int buffer_size)
+ void open(const T& dev, std::streamsize buffer_size)
{
if (flags_ & f_open)
boost::throw_exception(BOOST_IOSTREAMS_FAILURE("already open"));
if (buffer_size == -1)
buffer_size = default_filter_buffer_size;
- int max_length = cvt_.get().max_length();
+ std::streamsize max_length = cvt_.get().max_length();
buffer_size = (std::max)(buffer_size, 2 * max_length);
if (can_read::value) {
buf_.first().resize(buffer_size);
@@ -223,7 +223,7 @@ struct code_converter_impl {
//--------------Definition of converter---------------------------------------//
-#define BOOST_IOSTREAMS_CONVERTER_PARAMS() , int buffer_size = -1
+#define BOOST_IOSTREAMS_CONVERTER_PARAMS() , std::streamsize buffer_size = -1
#define BOOST_IOSTREAMS_CONVERTER_ARGS() , buffer_size
template<typename Device, typename Codecvt, typename Alloc>
diff --git a/boost/iostreams/detail/config/codecvt.hpp b/boost/iostreams/detail/config/codecvt.hpp
index b525c8435b..6519ddcd44 100644
--- a/boost/iostreams/detail/config/codecvt.hpp
+++ b/boost/iostreams/detail/config/codecvt.hpp
@@ -20,7 +20,8 @@
//------------------Support for codecvt with user-defined state types---------//
#if defined(__MSL_CPP__) || defined(__LIBCOMO__) || \
- BOOST_WORKAROUND(_STLPORT_VERSION, <= 0x450) \
+ BOOST_WORKAROUND(_STLPORT_VERSION, <= 0x450) || \
+ defined(_LIBCPP_VERSION) \
/**/
# define BOOST_IOSTREAMS_NO_PRIMARY_CODECVT_DEFINITION
#endif
diff --git a/boost/iostreams/detail/config/fpos.hpp b/boost/iostreams/detail/config/fpos.hpp
index e76cc30211..de8bdb84aa 100644
--- a/boost/iostreams/detail/config/fpos.hpp
+++ b/boost/iostreams/detail/config/fpos.hpp
@@ -25,7 +25,7 @@
#include <boost/config.hpp>
# if (defined(_YVALS) || defined(_CPPLIB_VER)) && !defined(__SGI_STL_PORT) && \
- !defined(_STLPORT_VERSION) && !defined(__QNX__)
+ !defined(_STLPORT_VERSION) && !defined(__QNX__) && !defined(_VX_CPU)
/**/
#include <boost/iostreams/detail/ios.hpp>
diff --git a/boost/iostreams/detail/config/unreachable_return.hpp b/boost/iostreams/detail/config/unreachable_return.hpp
index 97b3709952..65fba609de 100644
--- a/boost/iostreams/detail/config/unreachable_return.hpp
+++ b/boost/iostreams/detail/config/unreachable_return.hpp
@@ -13,7 +13,6 @@
#include <boost/config.hpp>
-// If Boost.Exception has BOOST_ATTRIBUTE_NORETURN
#if defined(_MSC_VER) || defined(__GNUC__)
#define BOOST_IOSTREAMS_UNREACHABLE_RETURN(x) \
BOOST_UNREACHABLE_RETURN(x)
diff --git a/boost/iostreams/detail/streambuf/indirect_streambuf.hpp b/boost/iostreams/detail/streambuf/indirect_streambuf.hpp
index 8da5ef3c50..90e1e11531 100644
--- a/boost/iostreams/detail/streambuf/indirect_streambuf.hpp
+++ b/boost/iostreams/detail/streambuf/indirect_streambuf.hpp
@@ -107,7 +107,7 @@ private:
bool can_read() const { return is_convertible<Mode, input>::value; }
bool can_write() const { return is_convertible<Mode, output>::value; }
bool output_buffered() const { return (flags_ & f_output_buffered) != 0; }
- bool shared_buffer() const { return is_convertible<Mode, seekable>::value; }
+ bool shared_buffer() const { return is_convertible<Mode, seekable>::value || is_convertible<Mode, dual_seekable>::value; }
void set_flags(int f) { flags_ = f; }
//----------State changing functions--------------------------------------//
@@ -169,16 +169,16 @@ void indirect_streambuf<T, Tr, Alloc, Mode>::open
pback_size_ = (std::max)(std::streamsize(2), pback_size); // STLPort needs 2.
std::streamsize size =
pback_size_ +
- ( buffer_size ? buffer_size: 1 );
- in().resize(size);
+ ( buffer_size ? buffer_size: std::streamsize(1) );
+ in().resize(static_cast<int>(size));
if (!shared_buffer())
init_get_area();
}
// Construct output buffer.
if (can_write() && !shared_buffer()) {
- if (buffer_size != 0)
- out().resize(buffer_size);
+ if (buffer_size != std::streamsize(0))
+ out().resize(static_cast<int>(buffer_size));
init_put_area();
}
@@ -346,16 +346,31 @@ indirect_streambuf<T, Tr, Alloc, Mode>::seek_impl
if ( gptr() != 0 && way == BOOST_IOS::cur && which == BOOST_IOS::in &&
eback() - gptr() <= off && off <= egptr() - gptr() )
{ // Small seek optimization
- gbump(off);
- return obj().seek(0, BOOST_IOS::cur, BOOST_IOS::in, next_) -
+ gbump(static_cast<int>(off));
+ return obj().seek(stream_offset(0), BOOST_IOS::cur, BOOST_IOS::in, next_) -
static_cast<off_type>(egptr() - gptr());
}
if (pptr() != 0)
this->BOOST_IOSTREAMS_PUBSYNC(); // sync() confuses VisualAge 6.
if (way == BOOST_IOS::cur && gptr())
off -= static_cast<off_type>(egptr() - gptr());
- setg(0, 0, 0);
- setp(0, 0);
+ bool two_head = is_convertible<category, dual_seekable>::value ||
+ is_convertible<category, bidirectional_seekable>::value;
+ if (two_head) {
+ BOOST_IOS::openmode both = BOOST_IOS::in | BOOST_IOS::out;
+ if ((which & both) == both)
+ boost::throw_exception(bad_seek());
+ if (which & BOOST_IOS::in) {
+ setg(0, 0, 0);
+ }
+ if (which & BOOST_IOS::out) {
+ setp(0, 0);
+ }
+ }
+ else {
+ setg(0, 0, 0);
+ setp(0, 0);
+ }
return obj().seek(off, way, which, next_);
}
@@ -394,7 +409,7 @@ void indirect_streambuf<T, Tr, Alloc, Mode>::sync_impl()
else {
const char_type* ptr = pptr();
setp(out().begin() + amt, out().end());
- pbump(ptr - pptr());
+ pbump(static_cast<int>(ptr - pptr()));
}
}
}
@@ -413,8 +428,10 @@ template<typename T, typename Tr, typename Alloc, typename Mode>
void indirect_streambuf<T, Tr, Alloc, Mode>::init_put_area()
{
using namespace std;
- if (shared_buffer() && gptr() != 0)
+ if (shared_buffer() && gptr() != 0) {
+ obj().seek(static_cast<off_type>(gptr() - egptr()), BOOST_IOS::cur, BOOST_IOS::in, next_);
setg(0, 0, 0);
+ }
if (output_buffered())
setp(out().begin(), out().end());
else
diff --git a/boost/iostreams/device/mapped_file.hpp b/boost/iostreams/device/mapped_file.hpp
index 8ee11c47dd..1332beabd1 100644
--- a/boost/iostreams/device/mapped_file.hpp
+++ b/boost/iostreams/device/mapped_file.hpp
@@ -309,7 +309,7 @@ public:
const char* const_data() const { return delegate_.data(); }
iterator begin() const { return data(); }
const_iterator const_begin() const { return const_data(); }
- iterator end() const { return data() + size(); }
+ iterator end() const;
const_iterator const_end() const { return const_data() + size(); }
//--------------Query admissible offsets----------------------------------//
@@ -469,6 +469,9 @@ void mapped_file::open(
inline char* mapped_file::data() const
{ return (flags() != readonly) ? const_cast<char*>(delegate_.data()) : 0; }
+inline mapped_file::iterator mapped_file::end() const
+{ return (flags() != readonly) ? data() + size() : 0; }
+
//------------------Implementation of mapped_file_sink------------------------//
template<typename Path>
diff --git a/boost/iostreams/device/null.hpp b/boost/iostreams/device/null.hpp
index 031c3e2fa2..a3943d7436 100644
--- a/boost/iostreams/device/null.hpp
+++ b/boost/iostreams/device/null.hpp
@@ -29,7 +29,7 @@ public:
public device_tag,
public closable_tag
{ };
- std::streamsize read(Ch*, std::streamsize) { return 0; }
+ std::streamsize read(Ch*, std::streamsize) { return -1; }
std::streamsize write(const Ch*, std::streamsize n) { return n; }
std::streampos seek( stream_offset, BOOST_IOS::seekdir,
BOOST_IOS::openmode =
diff --git a/boost/iostreams/filter/bzip2.hpp b/boost/iostreams/filter/bzip2.hpp
index 7c1d1efc10..029338d1c6 100644
--- a/boost/iostreams/filter/bzip2.hpp
+++ b/boost/iostreams/filter/bzip2.hpp
@@ -87,9 +87,9 @@ const bool default_small = false;
struct bzip2_params {
// Non-explicit constructor for compression.
- bzip2_params( int block_size = bzip2::default_block_size,
- int work_factor = bzip2::default_work_factor )
- : block_size(block_size), work_factor(work_factor)
+ bzip2_params( int block_size_ = bzip2::default_block_size,
+ int work_factor_ = bzip2::default_work_factor )
+ : block_size(block_size_), work_factor(work_factor_)
{ }
// Constructor for decompression.
@@ -242,7 +242,7 @@ public:
typedef typename base_type::char_type char_type;
typedef typename base_type::category category;
basic_bzip2_compressor( const bzip2_params& = bzip2::default_block_size,
- int buffer_size = default_device_buffer_size );
+ std::streamsize buffer_size = default_device_buffer_size );
};
BOOST_IOSTREAMS_PIPABLE(basic_bzip2_compressor, 1)
@@ -264,7 +264,7 @@ public:
typedef typename base_type::char_type char_type;
typedef typename base_type::category category;
basic_bzip2_decompressor( bool small = bzip2::default_small,
- int buffer_size = default_device_buffer_size );
+ std::streamsize buffer_size = default_device_buffer_size );
};
BOOST_IOSTREAMS_PIPABLE(basic_bzip2_decompressor, 1)
@@ -386,7 +386,7 @@ inline void bzip2_decompressor_impl<Alloc>::init()
template<typename Alloc>
basic_bzip2_compressor<Alloc>::basic_bzip2_compressor
- (const bzip2_params& p, int buffer_size)
+ (const bzip2_params& p, std::streamsize buffer_size)
: base_type(buffer_size, p)
{ }
@@ -394,7 +394,7 @@ basic_bzip2_compressor<Alloc>::basic_bzip2_compressor
template<typename Alloc>
basic_bzip2_decompressor<Alloc>::basic_bzip2_decompressor
- (bool small, int buffer_size)
+ (bool small, std::streamsize buffer_size)
: base_type(buffer_size, small)
{ }
diff --git a/boost/iostreams/filter/gzip.hpp b/boost/iostreams/filter/gzip.hpp
index fb18224ea1..d7939c82d2 100644
--- a/boost/iostreams/filter/gzip.hpp
+++ b/boost/iostreams/filter/gzip.hpp
@@ -32,7 +32,7 @@
#include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp>
#include <boost/iostreams/detail/adapter/range_adapter.hpp>
#include <boost/iostreams/detail/char_traits.hpp>
-#include <boost/iostreams/detail/ios.hpp> // failure.
+#include <boost/iostreams/detail/ios.hpp> // failure, streamsize.
#include <boost/iostreams/detail/error.hpp>
#include <boost/iostreams/operations.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
@@ -143,11 +143,11 @@ struct gzip_params : zlib_params {
int window_bits = gzip::default_window_bits,
int mem_level = gzip::default_mem_level,
int strategy = gzip::default_strategy,
- std::string file_name = "",
- std::string comment = "",
- std::time_t mtime = 0 )
+ std::string file_name_ = "",
+ std::string comment_ = "",
+ std::time_t mtime_ = 0 )
: zlib_params(level, method, window_bits, mem_level, strategy),
- file_name(file_name), comment(comment), mtime(mtime)
+ file_name(file_name_), comment(comment_), mtime(mtime_)
{ }
std::string file_name;
std::string comment;
@@ -197,7 +197,7 @@ public:
closable_tag
{ };
basic_gzip_compressor( const gzip_params& = gzip::default_compression,
- int buffer_size = default_device_buffer_size );
+ std::streamsize buffer_size = default_device_buffer_size );
template<typename Source>
std::streamsize read(Source& src, char_type* s, std::streamsize n)
@@ -285,7 +285,7 @@ private:
boost::iostreams::put(next, static_cast<char>(0xFF & (n >> 24)));
}
template<typename Sink>
- static void write_long(long n, Sink& next, boost::mpl::false_)
+ static void write_long(long, Sink&, boost::mpl::false_)
{
}
template<typename Sink>
@@ -411,7 +411,7 @@ public:
closable_tag
{ };
basic_gzip_decompressor( int window_bits = gzip::default_window_bits,
- int buffer_size = default_device_buffer_size );
+ std::streamsize buffer_size = default_device_buffer_size );
template<typename Sink>
std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
@@ -505,7 +505,7 @@ public:
if (footer_.done()) {
if (footer_.crc() != this->crc())
boost::throw_exception(gzip_error(gzip::bad_crc));
- int c = boost::iostreams::get(peek);
+ c = boost::iostreams::get(peek);
if (traits_type::is_eof(c)) {
state_ = s_done;
} else {
@@ -645,7 +645,7 @@ typedef basic_gzip_decompressor<> gzip_decompressor;
template<typename Alloc>
basic_gzip_compressor<Alloc>::basic_gzip_compressor
- (const gzip_params& p, int buffer_size)
+ (const gzip_params& p, std::streamsize buffer_size)
: base_type(normalize_params(p), buffer_size),
offset_(0), flags_(0)
{
@@ -731,7 +731,7 @@ std::streamsize basic_gzip_compressor<Alloc>::read_string
template<typename Alloc>
basic_gzip_decompressor<Alloc>::basic_gzip_decompressor
- (int window_bits, int buffer_size)
+ (int window_bits, std::streamsize buffer_size)
: base_type(make_params(window_bits), buffer_size),
state_(s_start)
{ }
diff --git a/boost/iostreams/filter/symmetric.hpp b/boost/iostreams/filter/symmetric.hpp
index 57ceea7727..f18089f4fb 100644
--- a/boost/iostreams/filter/symmetric.hpp
+++ b/boost/iostreams/filter/symmetric.hpp
@@ -42,13 +42,14 @@
#endif
#include <boost/assert.hpp>
-#include <memory> // allocator, auto_ptr.
+#include <memory> // allocator.
#include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME.
#include <boost/iostreams/char_traits.hpp>
#include <boost/iostreams/constants.hpp> // buffer size.
#include <boost/iostreams/detail/buffer.hpp>
#include <boost/iostreams/detail/char_traits.hpp>
#include <boost/iostreams/detail/config/limits.hpp>
+#include <boost/iostreams/detail/ios.hpp> // streamsize.
#include <boost/iostreams/detail/template_params.hpp>
#include <boost/iostreams/traits.hpp>
#include <boost/iostreams/operations.hpp> // read, write.
@@ -85,7 +86,7 @@ public:
#define BOOST_PP_LOCAL_MACRO(n) \
BOOST_IOSTREAMS_TEMPLATE_PARAMS(n, T) \
explicit symmetric_filter( \
- int buffer_size BOOST_PP_COMMA_IF(n) \
+ std::streamsize buffer_size BOOST_PP_COMMA_IF(n) \
BOOST_PP_ENUM_BINARY_PARAMS(n, const T, &t) ) \
: pimpl_(new impl(buffer_size BOOST_PP_COMMA_IF(n) \
BOOST_PP_ENUM_PARAMS(n, t))) \
@@ -252,7 +253,7 @@ private:
// Expands to a sequence of ctors which forward to SymmetricFilter.
#define BOOST_PP_LOCAL_MACRO(n) \
BOOST_IOSTREAMS_TEMPLATE_PARAMS(n, T) \
- impl( int buffer_size BOOST_PP_COMMA_IF(n) \
+ impl( std::streamsize buffer_size BOOST_PP_COMMA_IF(n) \
BOOST_PP_ENUM_BINARY_PARAMS(n, const T, &t) ) \
: SymmetricFilter(BOOST_PP_ENUM_PARAMS(n, t)), \
buf_(buffer_size), state_(0) \
diff --git a/boost/iostreams/filter/zlib.hpp b/boost/iostreams/filter/zlib.hpp
index 848af89255..3d0de14a70 100644
--- a/boost/iostreams/filter/zlib.hpp
+++ b/boost/iostreams/filter/zlib.hpp
@@ -110,16 +110,16 @@ const bool default_noheader = false;
struct zlib_params {
// Non-explicit constructor.
- zlib_params( int level = zlib::default_compression,
- int method = zlib::deflated,
- int window_bits = zlib::default_window_bits,
- int mem_level = zlib::default_mem_level,
- int strategy = zlib::default_strategy,
- bool noheader = zlib::default_noheader,
- bool calculate_crc = zlib::default_crc )
- : level(level), method(method), window_bits(window_bits),
- mem_level(mem_level), strategy(strategy),
- noheader(noheader), calculate_crc(calculate_crc)
+ zlib_params( int level_ = zlib::default_compression,
+ int method_ = zlib::deflated,
+ int window_bits_ = zlib::default_window_bits,
+ int mem_level_ = zlib::default_mem_level,
+ int strategy_ = zlib::default_strategy,
+ bool noheader_ = zlib::default_noheader,
+ bool calculate_crc_ = zlib::default_crc )
+ : level(level_), method(method_), window_bits(window_bits_),
+ mem_level(mem_level_), strategy(strategy_),
+ noheader(noheader_), calculate_crc(calculate_crc_)
{ }
int level;
int method;
@@ -263,7 +263,7 @@ public:
typedef typename base_type::char_type char_type;
typedef typename base_type::category category;
basic_zlib_compressor( const zlib_params& = zlib::default_compression,
- int buffer_size = default_device_buffer_size );
+ std::streamsize buffer_size = default_device_buffer_size );
zlib::ulong crc() { return this->filter().crc(); }
int total_in() { return this->filter().total_in(); }
};
@@ -287,9 +287,9 @@ public:
typedef typename base_type::char_type char_type;
typedef typename base_type::category category;
basic_zlib_decompressor( int window_bits = zlib::default_window_bits,
- int buffer_size = default_device_buffer_size );
+ std::streamsize buffer_size = default_device_buffer_size );
basic_zlib_decompressor( const zlib_params& p,
- int buffer_size = default_device_buffer_size );
+ std::streamsize buffer_size = default_device_buffer_size );
zlib::ulong crc() { return this->filter().crc(); }
int total_out() { return this->filter().total_out(); }
bool eof() { return this->filter().eof(); }
@@ -347,7 +347,7 @@ bool zlib_compressor_impl<Alloc>::filter
int result = xdeflate(flush ? zlib::finish : zlib::no_flush);
after(src_begin, dest_begin, true);
zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result);
- return result != zlib::stream_end;
+ return result != zlib::stream_end;
}
template<typename Alloc>
@@ -396,19 +396,19 @@ void zlib_decompressor_impl<Alloc>::close() {
template<typename Alloc>
basic_zlib_compressor<Alloc>::basic_zlib_compressor
- (const zlib_params& p, int buffer_size)
+ (const zlib_params& p, std::streamsize buffer_size)
: base_type(buffer_size, p) { }
//------------------Implementation of zlib_decompressor-----------------------//
template<typename Alloc>
basic_zlib_decompressor<Alloc>::basic_zlib_decompressor
- (int window_bits, int buffer_size)
+ (int window_bits, std::streamsize buffer_size)
: base_type(buffer_size, window_bits) { }
template<typename Alloc>
basic_zlib_decompressor<Alloc>::basic_zlib_decompressor
- (const zlib_params& p, int buffer_size)
+ (const zlib_params& p, std::streamsize buffer_size)
: base_type(buffer_size, p) { }
//----------------------------------------------------------------------------//
diff --git a/boost/iostreams/invert.hpp b/boost/iostreams/invert.hpp
index 1d3787e13f..d4a17bf7f3 100644
--- a/boost/iostreams/invert.hpp
+++ b/boost/iostreams/invert.hpp
@@ -73,7 +73,7 @@ public:
{ }
template<typename Source>
- std::streamsize read(Source& src, char* s, std::streamsize n)
+ std::streamsize read(Source& src, char_type* s, std::streamsize n)
{
typedef detail::counted_array_sink<char_type> array_sink;
typedef composite<filter_ref, array_sink> filtered_array_sink;
@@ -101,7 +101,7 @@ public:
}
template<typename Sink>
- std::streamsize write(Sink& dest, const char* s, std::streamsize n)
+ std::streamsize write(Sink& dest, const char_type* s, std::streamsize n)
{
typedef detail::counted_array_source<char_type> array_source;
typedef composite<filter_ref, array_source> filtered_array_source;
diff --git a/boost/iterator/function_input_iterator.hpp b/boost/iterator/function_input_iterator.hpp
index 8a793df1b7..f3e9de92e4 100644
--- a/boost/iterator/function_input_iterator.hpp
+++ b/boost/iterator/function_input_iterator.hpp
@@ -9,6 +9,7 @@
#ifndef BOOST_FUNCTION_INPUT_ITERATOR
#define BOOST_FUNCTION_INPUT_ITERATOR
+#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/function_types/is_function_pointer.hpp>
@@ -17,6 +18,7 @@
#include <boost/iterator/iterator_facade.hpp>
#include <boost/none.hpp>
#include <boost/optional/optional.hpp>
+#include <boost/utility/result_of.hpp>
namespace boost {
@@ -28,9 +30,9 @@ namespace iterators {
class function_input_iterator
: public iterator_facade<
function_input_iterator<Function, Input>,
- typename Function::result_type,
+ BOOST_DEDUCED_TYPENAME result_of<Function ()>::type,
single_pass_traversal_tag,
- typename Function::result_type const &
+ BOOST_DEDUCED_TYPENAME result_of<Function ()>::type const &
>
{
public:
@@ -46,7 +48,7 @@ namespace iterators {
++state;
}
- typename Function::result_type const &
+ BOOST_DEDUCED_TYPENAME result_of<Function ()>::type const &
dereference() const {
return (value ? value : value = (*f)()).get();
}
@@ -58,7 +60,7 @@ namespace iterators {
private:
Function * f;
Input state;
- mutable optional<typename Function::result_type> value;
+ mutable optional<BOOST_DEDUCED_TYPENAME result_of<Function ()>::type> value;
};
template <class Function, class Input>
diff --git a/boost/lexical_cast/detail/converter_lexical_streams.hpp b/boost/lexical_cast/detail/converter_lexical_streams.hpp
index 86c9c6d2c0..7bee25e1ad 100644
--- a/boost/lexical_cast/detail/converter_lexical_streams.hpp
+++ b/boost/lexical_cast/detail/converter_lexical_streams.hpp
@@ -576,12 +576,13 @@ namespace boost {
#endif
#if defined(BOOST_NO_STRINGSTREAM)
- std::istrstream stream(start, finish - start);
+ std::istrstream stream(start, static_cast<std::istrstream::streamsize>(finish - start));
#else
- BOOST_DEDUCED_TYPENAME out_stream_helper_trait<CharT, Traits>::buffer_t buf;
+ typedef BOOST_DEDUCED_TYPENAME out_stream_helper_trait<CharT, Traits>::buffer_t buffer_t;
+ buffer_t buf;
// Usually `istream` and `basic_istream` do not modify
// content of buffer; `buffer_t` assures that this is true
- buf.setbuf(const_cast<CharT*>(start), finish - start);
+ buf.setbuf(const_cast<CharT*>(start), static_cast<typename buffer_t::streamsize>(finish - start));
#if defined(BOOST_NO_STD_LOCALE)
std::istream stream(&buf);
#else
diff --git a/boost/make_unique.hpp b/boost/make_unique.hpp
index 4dc82c3c7a..7189d6e4ec 100644
--- a/boost/make_unique.hpp
+++ b/boost/make_unique.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_MAKE_UNIQUE_HPP_INCLUDED
#define BOOST_MAKE_UNIQUE_HPP_INCLUDED
diff --git a/boost/math/special_functions/acosh.hpp b/boost/math/special_functions/acosh.hpp
index 0af5c94c14..3b7edbad3f 100644
--- a/boost/math/special_functions/acosh.hpp
+++ b/boost/math/special_functions/acosh.hpp
@@ -36,7 +36,7 @@ namespace boost
{
BOOST_MATH_STD_USING
- if(x < 1)
+ if((x < 1) || (boost::math::isnan)(x))
{
return policies::raise_domain_error<T>(
"boost::math::acosh<%1%>(%1%)",
diff --git a/boost/math/special_functions/asinh.hpp b/boost/math/special_functions/asinh.hpp
index a863e68854..e55a356284 100644
--- a/boost/math/special_functions/asinh.hpp
+++ b/boost/math/special_functions/asinh.hpp
@@ -36,6 +36,12 @@ namespace boost
{
BOOST_MATH_STD_USING
+ if((boost::math::isnan)(x))
+ {
+ return policies::raise_domain_error<T>(
+ "boost::math::asinh<%1%>(%1%)",
+ "asinh requires a finite argument, but got x = %1%.", x, pol);
+ }
if (x >= tools::forth_root_epsilon<T>())
{
if (x > 1 / tools::root_epsilon<T>())
diff --git a/boost/math/special_functions/atanh.hpp b/boost/math/special_functions/atanh.hpp
index 2c5e3f4b78..871a465a8c 100644
--- a/boost/math/special_functions/atanh.hpp
+++ b/boost/math/special_functions/atanh.hpp
@@ -51,6 +51,12 @@ namespace boost
function,
"atanh requires x <= 1, but got x = %1%.", x, pol);
}
+ else if((boost::math::isnan)(x))
+ {
+ return policies::raise_domain_error<T>(
+ function,
+ "atanh requires -1 <= x <= 1, but got x = %1%.", x, pol);
+ }
else if(x < -1 + tools::epsilon<T>())
{
// -Infinity:
diff --git a/boost/math/special_functions/bessel.hpp b/boost/math/special_functions/bessel.hpp
index 1b57e0a873..69f931bd5a 100644
--- a/boost/math/special_functions/bessel.hpp
+++ b/boost/math/special_functions/bessel.hpp
@@ -206,7 +206,7 @@ T cyl_bessel_i_imp(T v, T x, const Policy& pol)
}
return sqrt(2 / (x * constants::pi<T>())) * sinh(x);
}
- if(policies::digits<T, Policy>() <= 64)
+ if(policies::digits<T, Policy>() <= 113)
{
if(v == 0)
{
@@ -572,7 +572,7 @@ inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k(
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
- typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
+ typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag128 tag_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
diff --git a/boost/math/special_functions/cbrt.hpp b/boost/math/special_functions/cbrt.hpp
index 0fc6e0742a..c34ad39949 100644
--- a/boost/math/special_functions/cbrt.hpp
+++ b/boost/math/special_functions/cbrt.hpp
@@ -68,7 +68,8 @@ T cbrt_imp(T z, const Policy& pol)
static_cast<T>(1.2599210498948731647672106072782), // 2^1/3
static_cast<T>(1.5874010519681994747517056392723), // 2^2/3
};
-
+ if((boost::math::isinf)(z) || (z == 0))
+ return z;
if(!(boost::math::isfinite)(z))
{
return policies::raise_domain_error("boost::math::cbrt<%1%>(%1%)", "Argument to function must be finite but got %1%.", z, pol);
@@ -80,8 +81,6 @@ T cbrt_imp(T z, const Policy& pol)
z = -z;
sign = -sign;
}
- if(z == 0)
- return 0;
T guess = frexp(z, &i_exp);
int original_i_exp = i_exp; // save for later
diff --git a/boost/math/special_functions/detail/bessel_i0.hpp b/boost/math/special_functions/detail/bessel_i0.hpp
index 676eb71511..5896db8f76 100644
--- a/boost/math/special_functions/detail/bessel_i0.hpp
+++ b/boost/math/special_functions/detail/bessel_i0.hpp
@@ -1,4 +1,5 @@
// Copyright (c) 2006 Xiaogang Zhang
+// Copyright (c) 2017 John Maddock
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -15,28 +16,45 @@
#include <boost/assert.hpp>
// Modified Bessel function of the first kind of order zero
-// minimax rational approximations on intervals, see
-// Blair and Edwards, Chalk River Report AECL-4928, 1974
+// we use the approximating forms derived in:
+// "Rational Approximations for the Modified Bessel Function of the First Kind – I0(x) for Computations with Double Precision"
+// by Pavel Holoborodko,
+// see http://www.advanpix.com/2015/11/11/rational-approximations-for-the-modified-bessel-function-of-the-first-kind-i0-computations-double-precision
+// The actual coefficients used are our own, and extend Pavel's work to precision's other than double.
namespace boost { namespace math { namespace detail{
template <typename T>
-T bessel_i0(T x);
+T bessel_i0(const T& x);
-template <class T>
+template <class T, class tag>
struct bessel_i0_initializer
{
struct init
{
init()
{
- do_init();
+ do_init(tag());
}
- static void do_init()
+ static void do_init(const mpl::int_<64>&)
{
bessel_i0(T(1));
+ bessel_i0(T(8));
+ bessel_i0(T(12));
+ bessel_i0(T(40));
+ bessel_i0(T(101));
}
- void force_instantiate()const{}
+ static void do_init(const mpl::int_<113>&)
+ {
+ bessel_i0(T(1));
+ bessel_i0(T(10));
+ bessel_i0(T(20));
+ bessel_i0(T(40));
+ bessel_i0(T(101));
+ }
+ template <class U>
+ static void do_init(const U&) {}
+ void force_instantiate()const {}
};
static const init initializer;
static void force_instantiate()
@@ -45,82 +63,489 @@ struct bessel_i0_initializer
}
};
-template <class T>
-const typename bessel_i0_initializer<T>::init bessel_i0_initializer<T>::initializer;
+template <class T, class tag>
+const typename bessel_i0_initializer<T, tag>::init bessel_i0_initializer<T, tag>::initializer;
+
+template <typename T, int N>
+T bessel_i0_imp(const T&, const mpl::int_<N>&)
+{
+ BOOST_ASSERT(0);
+ return 0;
+}
+
+template <typename T>
+T bessel_i0_imp(const T& x, const mpl::int_<24>&)
+{
+ BOOST_MATH_STD_USING
+ if(x < 7.75)
+ {
+ // Max error in interpolated form: 3.929e-08
+ // Max Error found at float precision = Poly: 1.991226e-07
+ static const float P[] = {
+ 1.00000003928615375e+00f,
+ 2.49999576572179639e-01f,
+ 2.77785268558399407e-02f,
+ 1.73560257755821695e-03f,
+ 6.96166518788906424e-05f,
+ 1.89645733877137904e-06f,
+ 4.29455004657565361e-08f,
+ 3.90565476357034480e-10f,
+ 1.48095934745267240e-11f
+ };
+ T a = x * x / 4;
+ return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
+ }
+ else if(x < 50)
+ {
+ // Max error in interpolated form: 5.195e-08
+ // Max Error found at float precision = Poly: 8.502534e-08
+ static const float P[] = {
+ 3.98942651588301770e-01f,
+ 4.98327234176892844e-02f,
+ 2.91866904423115499e-02f,
+ 1.35614940793742178e-02f,
+ 1.31409251787866793e-01f
+ };
+ return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ }
+ else
+ {
+ // Max error in interpolated form: 1.782e-09
+ // Max Error found at float precision = Poly: 6.473568e-08
+ static const float P[] = {
+ 3.98942391532752700e-01f,
+ 4.98455950638200020e-02f,
+ 2.94835666900682535e-02f
+ };
+ T ex = exp(x / 2);
+ T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ result *= ex;
+ return result;
+ }
+}
+
+template <typename T>
+T bessel_i0_imp(const T& x, const mpl::int_<53>&)
+{
+ BOOST_MATH_STD_USING
+ if(x < 7.75)
+ {
+ // Bessel I0 over[10 ^ -16, 7.75]
+ // Max error in interpolated form : 3.042e-18
+ // Max Error found at double precision = Poly : 5.106609e-16 Cheb : 5.239199e-16
+ static const double P[] = {
+ 1.00000000000000000e+00,
+ 2.49999999999999909e-01,
+ 2.77777777777782257e-02,
+ 1.73611111111023792e-03,
+ 6.94444444453352521e-05,
+ 1.92901234513219920e-06,
+ 3.93675991102510739e-08,
+ 6.15118672704439289e-10,
+ 7.59407002058973446e-12,
+ 7.59389793369836367e-14,
+ 6.27767773636292611e-16,
+ 4.34709704153272287e-18,
+ 2.63417742690109154e-20,
+ 1.13943037744822825e-22,
+ 9.07926920085624812e-25
+ };
+ T a = x * x / 4;
+ return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
+ }
+ else if(x < 500)
+ {
+ // Max error in interpolated form : 1.685e-16
+ // Max Error found at double precision = Poly : 2.575063e-16 Cheb : 2.247615e+00
+ static const double P[] = {
+ 3.98942280401425088e-01,
+ 4.98677850604961985e-02,
+ 2.80506233928312623e-02,
+ 2.92211225166047873e-02,
+ 4.44207299493659561e-02,
+ 1.30970574605856719e-01,
+ -3.35052280231727022e+00,
+ 2.33025711583514727e+02,
+ -1.13366350697172355e+04,
+ 4.24057674317867331e+05,
+ -1.23157028595698731e+07,
+ 2.80231938155267516e+08,
+ -5.01883999713777929e+09,
+ 7.08029243015109113e+10,
+ -7.84261082124811106e+11,
+ 6.76825737854096565e+12,
+ -4.49034849696138065e+13,
+ 2.24155239966958995e+14,
+ -8.13426467865659318e+14,
+ 2.02391097391687777e+15,
+ -3.08675715295370878e+15,
+ 2.17587543863819074e+15
+ };
+ return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ }
+ else
+ {
+ // Max error in interpolated form : 2.437e-18
+ // Max Error found at double precision = Poly : 1.216719e-16
+ static const double P[] = {
+ 3.98942280401432905e-01,
+ 4.98677850491434560e-02,
+ 2.80506308916506102e-02,
+ 2.92179096853915176e-02,
+ 4.53371208762579442e-02
+ };
+ T ex = exp(x / 2);
+ T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ result *= ex;
+ return result;
+ }
+}
template <typename T>
-T bessel_i0(T x)
+T bessel_i0_imp(const T& x, const mpl::int_<64>&)
{
- bessel_i0_initializer<T>::force_instantiate();
-
- static const T P1[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2335582639474375249e+15)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.5050369673018427753e+14)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.2940087627407749166e+13)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.4925101247114157499e+11)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.1912746104985237192e+10)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0313066708737980747e+08)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.9545626019847898221e+05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.4125195876041896775e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -7.0935347449210549190e+00)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.5453977791786851041e-02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.5172644670688975051e-05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.0517226450451067446e-08)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.6843448573468483278e-11)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.5982226675653184646e-14)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.2487866627945699800e-18)),
- };
- static const T Q1[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2335582639474375245e+15)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.8858692566751002988e+12)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2207067397808979846e+10)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0377081058062166144e+07)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.8527560179962773045e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
- };
- static const T P2[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2210262233306573296e-04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3067392038106924055e-02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.4700805721174453923e-01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.5674518371240761397e+00)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.3517945679239481621e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.1611322818701131207e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -9.6090021968656180000e+00)),
- };
- static const T Q2[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.5194330231005480228e-04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.2547697594819615062e-02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.1151759188741312645e+00)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3982595353892851542e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.0228002066743340583e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.5539563258012929600e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.1446690275135491500e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
- };
- T value, factor, r;
-
- BOOST_MATH_STD_USING
- using namespace boost::math::tools;
-
- BOOST_ASSERT(x >= 0); // negative x is handled before we get here
- if (x == 0)
- {
- return static_cast<T>(1);
- }
- if (x <= 15) // x in (0, 15]
- {
- T y = x * x;
- value = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
- }
- else // x in (15, \infty)
- {
- T y = 1 / x - T(1) / 15;
- r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
- factor = exp(x) / sqrt(x);
- value = factor * r;
- }
-
- return value;
+ BOOST_MATH_STD_USING
+ if(x < 7.75)
+ {
+ // Bessel I0 over[10 ^ -16, 7.75]
+ // Max error in interpolated form : 3.899e-20
+ // Max Error found at float80 precision = Poly : 1.770840e-19
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 9.99999999999999999961011629e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.50000000000000001321873912e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.77777777777777703400424216e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.73611111111112764793802701e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 6.94444444444251461247253525e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.92901234569262206386118739e-06),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.93675988851131457141005209e-08),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 6.15118734688297476454205352e-10),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 7.59405797058091016449222685e-12),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 7.59406599631719800679835140e-14),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 6.27598961062070013516660425e-16),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.35920318970387940278362992e-18),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.57372492687715452949437981e-20),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.33908663475949906992942204e-22),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 5.15976668870980234582896010e-25),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.46240478946376069211156548e-27)
+ };
+ T a = x * x / 4;
+ return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
+ }
+ else if(x < 10)
+ {
+ // Maximum Deviation Found: 6.906e-21
+ // Expected Error Term : -6.903e-21
+ // Maximum Relative Change in Control Points : 1.631e-04
+ // Max Error found at float80 precision = Poly : 7.811948e-21
+ static const T Y = 4.051098823547363281250e-01f;
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 64, -6.158081780620616479492e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.883635969834048766148e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 7.892782002476195771920e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.478784996478070170327e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.988611837308006851257e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.140133766747436806179e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.117316447921276453271e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -2.942353667455141676001e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.493482682461387081534e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -5.228100538921466124653e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.195279248600467989454e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.601530760654337045917e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 9.504921137873298402679e+05)
+ };
+ return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x);
+ }
+ else if(x < 15)
+ {
+ // Maximum Deviation Found: 4.083e-21
+ // Expected Error Term : -4.025e-21
+ // Maximum Relative Change in Control Points : 1.304e-03
+ // Max Error found at float80 precision = Poly : 2.303527e-20
+ static const T Y = 4.033188819885253906250e-01f;
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.376373876116109401062e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.982899138682911273321e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.109477529533515397644e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.163760580110576407673e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.776501832837367371883e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.101478069227776656318e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.892071912448960299773e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -2.417739279982328117483e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.296963447724067390552e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.598589306710589358747e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 7.903662411851774878322e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -2.622677059040339516093e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 5.227776578828667629347e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.727797957441040896878e+07)
+ };
+ return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x);
+ }
+ else if(x < 50)
+ {
+ // Max error in interpolated form: 1.035e-21
+ // Max Error found at float80 precision = Poly: 1.885872e-21
+ static const T Y = 4.011702537536621093750e-01f;
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 64, -2.227973351806078464328e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.986778486088017419036e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.805066823812285310011e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.921443721160964964623e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.517504941996594744052e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 6.316922639868793684401e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.535891099168810015433e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.706078229522448308087e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.351015763079160914632e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -2.948809013999277355098e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.967598958582595361757e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -6.346924657995383019558e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 5.998794574259956613472e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.016371355801690142095e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.768791455631826490838e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.441995678177349895640e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.482292669974971387738e+09)
+ };
+ return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x);
+ }
+ else
+ {
+ // Bessel I0 over[50, INF]
+ // Max error in interpolated form : 5.587e-20
+ // Max Error found at float80 precision = Poly : 8.776852e-20
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401432677955074061e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.98677850501789875615574058e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.80506290908675604202206833e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.92194052159035901631494784e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.47422430732256364094681137e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 9.05971614435738691235525172e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.29180522595459823234266708e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 6.15122547776140254569073131e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 7.48491812136365376477357324e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -2.45569740166506688169730713e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 9.66857566379480730407063170e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -2.71924083955641197750323901e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 5.74276685704579268845870586e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -8.89753803265734681907148778e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 9.82590905134996782086242180e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -7.30623197145529889358596301e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.27310000726207055200805893e+10),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -6.64365417189215599168817064e+10)
+ };
+ T ex = exp(x / 2);
+ T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ result *= ex;
+ return result;
+ }
+}
+
+template <typename T>
+T bessel_i0_imp(const T& x, const mpl::int_<113>&)
+{
+ BOOST_MATH_STD_USING
+ if(x < 7.75)
+ {
+ // Bessel I0 over[10 ^ -34, 7.75]
+ // Max error in interpolated form : 1.274e-34
+ // Max Error found at float128 precision = Poly : 3.096091e-34
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0000000000000000000000000000000001273856e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.4999999999999999999999999999999107477496e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.7777777777777777777777777777881795230918e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.7361111111111111111111111106290091648808e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444444444444445629960334523101e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.9290123456790123456790105563456483249753e-06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.9367598891408415217940836339080514004844e-08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.1511873267825648777900014857992724731476e-10),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266233066162999610732449709209e-12),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266232783124723601470051895304e-14),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.2760813455591936763439337059117957836078e-16),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.3583898233049738471136482147779094353096e-18),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.5789288895299965395422423848480340736308e-20),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.3157800456718804437960453545507623434606e-22),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.8479113149412360748032684260932041506493e-25),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.2843403488398038539283241944594140493394e-27),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.9042925594356556196790242908697582021825e-30),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.4395919891312152120710245152115597111101e-32),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.7580986145276689333214547502373003196707e-35),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.6886514018062348877723837017198859723889e-37),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.8540558465757554512570197585002702777999e-40),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.4684706070226893763741850944911705726436e-43),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.0210715309399646335858150349406935414314e-45)
+ };
+ T a = x * x / 4;
+ return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
+ }
+ else if(x < 15)
+ {
+ // Bessel I0 over[7.75, 15]
+ // Max error in interpolated form : 7.534e-35
+ // Max Error found at float128 precision = Poly : 6.123912e-34
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.9999999999999999992388573069504617493518e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.5000000000000000007304739268173096975340e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.7777777777777777744261405400543564492074e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.7361111111111111209006987259719750726867e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444442399703186871329381908321e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.9290123456790126709286741580242189785431e-06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.9367598891408374246503061422528266924389e-08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.1511873267826068395343047827801353170966e-10),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281262673459688011737168286944521e-12),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281291583769928563167645746144508e-14),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.2760813455438840231126529638737436950274e-16),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.3583898233839583885132809584770578894948e-18),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.5789288891798658971960571838369339742994e-20),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.3157800470129311623308216856009970266088e-22),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.8479112701534604520063520412207286692581e-25),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.2843404822552330714586265081801727491890e-27),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.9042888166225242675881424439818162458179e-30),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.4396027771820721384198604723320045236973e-32),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.7577659910606076328136207973456511895030e-35),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.6896548123724136624716224328803899914646e-37),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.8285850162160539150210466453921758781984e-40),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.9419071894227736216423562425429524883562e-43),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.4720374049498608905571855665134539425038e-45),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.7763533278527958112907118930154738930378e-48),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.1213839473168678646697528580511702663617e-51),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.0648035313124146852372607519737686740964e-53),
+ -BOOST_MATH_BIG_CONSTANT(T, 113, 5.1255595184052024349371058585102280860878e-57),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.4652470895944157957727948355523715335882e-59)
+ };
+ T a = x * x / 4;
+ return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
+ }
+ else if(x < 30)
+ {
+ // Max error in interpolated form : 1.808e-34
+ // Max Error found at float128 precision = Poly : 2.399403e-34
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040870793650581242239624530714032e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867780576714783790784348982178607842250e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.8051948347934462928487999569249907599510e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.8971143420388958551176254291160976367263e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.8197359701715582763961322341827341098897e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.3430484862908317377522273217643346601271e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.7884507603213662610604413960838990199224e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.8304926482356755790062999202373909300514e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.8867173178574875515293357145875120137676e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.4261178812193528551544261731796888257644e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.6453010340778116475788083817762403540097e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -5.0432401330113978669454035365747869477960e+10),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.2462165331309799059332310595587606836357e+12),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.3299800389951335932792950236410844978273e+13),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.5748218240248714177527965706790413406639e+14),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.8330014378766930869945511450377736037385e+15),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.8494610073827453236940544799030787866218e+17),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.7244661371420647691301043350229977856476e+18),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.2386378807889388140099109087465781254321e+20),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.1104000573102013529518477353943384110982e+21),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.9426541092239879262282594572224300191016e+22),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.4061439136301913488512592402635688101020e+23),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.2836554760521986358980180942859101564671e+24),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.6270285589905206294944214795661236766988e+25),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.7278631455211972017740134341610659484259e+26),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.1971734473772196124736986948034978906801e+26),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.8669270707172568763908838463689093500098e+27),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.2368879358870281916900125550129211146626e+28),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.8296235063297831758204519071113999839858e+28),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.1253861666023020670144616019148954773662e+28),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.8809536950051955163648980306847791014734e+28) };
+ return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ }
+ else if(x < 100)
+ {
+ // Bessel I0 over[30, 100]
+ // Max error in interpolated form : 1.487e-34
+ // Max Error found at float128 precision = Poly : 1.929924e-34
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793996798658172135362278e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867785050179084714910130342157246539820e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.8050629090725751585266360464766768437048e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.9219405302833158254515212437025679637597e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.4742214371598631578107310396249912330627e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.0602983776478659136184969363625092585520e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.2839507231977478205885469900971893734770e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.8925739165733823730525449511456529001868e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.4238082222874015159424842335385854632223e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.6759648427182491050716309699208988458050e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.7292246491169360014875196108746167872215e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.1001411442786230340015781205680362993575e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.8277628835804873490331739499978938078848e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.1208326312801432038715638596517882759639e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.4813611580683862051838126076298945680803e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.1278197693321821164135890132925119054391e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.3190303792682886967459489059860595063574e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.1580767338646580750893606158043485767644e+10),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -5.0256008808415702780816006134784995506549e+11),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.9044186472918017896554580836514681614475e+13),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.2521078890073151875661384381880225635135e+14),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.3620352486836976842181057590770636605454e+15),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.0375525734060401555856465179734887312420e+16),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.6392664899881014534361728644608549445131e+16)
+ };
+ return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ }
+ else
+ {
+ // Bessel I0 over[100, INF]
+ // Max error in interpolated form : 5.459e-35
+ // Max Error found at float128 precision = Poly : 1.472240e-34
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793994605993438166526772e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867785050179084742493257495245185241487e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.8050629090725735167652437695397756897920e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.9219405302839307466358297347675795965363e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.4742214369972689474366968442268908028204e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.0602984099194778006610058410222616383078e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.2839502241666629677015839125593079416327e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.8926354981801627920292655818232972385750e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.4231921590621824187100989532173995000655e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.7264260959693775207585700654645245723497e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.3890136225398811195878046856373030127018e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.1999720924619285464910452647408431234369e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.2076909538525038580501368530598517194748e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.5684635141332367730007149159063086133399e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.5178192543258299267923025833141286569141e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.2966297919851965784482163987240461837728e+05) };
+ T ex = exp(x / 2);
+ T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ result *= ex;
+ return result;
+ }
+}
+
+template <typename T>
+T bessel_i0_imp(const T& x, const mpl::int_<0>&)
+{
+ if(boost::math::tools::digits<T>() <= 24)
+ return bessel_i0_imp(x, mpl::int_<24>());
+ else if(boost::math::tools::digits<T>() <= 53)
+ return bessel_i0_imp(x, mpl::int_<53>());
+ else if(boost::math::tools::digits<T>() <= 64)
+ return bessel_i0_imp(x, mpl::int_<64>());
+ else if(boost::math::tools::digits<T>() <= 113)
+ return bessel_i0_imp(x, mpl::int_<113>());
+ BOOST_ASSERT(0);
+ return 0;
+}
+
+template <typename T>
+inline T bessel_i0(const T& x)
+{
+ typedef mpl::int_<
+ std::numeric_limits<T>::digits == 0 ?
+ 0 :
+ std::numeric_limits<T>::digits <= 24 ?
+ 24 :
+ std::numeric_limits<T>::digits <= 53 ?
+ 53 :
+ std::numeric_limits<T>::digits <= 64 ?
+ 64 :
+ std::numeric_limits<T>::digits <= 113 ?
+ 113 : -1
+ > tag_type;
+
+ bessel_i0_initializer<T, tag_type>::force_instantiate();
+ return bessel_i0_imp(x, tag_type());
}
}}} // namespaces
diff --git a/boost/math/special_functions/detail/bessel_i1.hpp b/boost/math/special_functions/detail/bessel_i1.hpp
index b85bc67546..0f9ba96bd8 100644
--- a/boost/math/special_functions/detail/bessel_i1.hpp
+++ b/boost/math/special_functions/detail/bessel_i1.hpp
@@ -1,7 +1,9 @@
-// Copyright (c) 2006 Xiaogang Zhang
-// 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)
+// Modified Bessel function of the first kind of order zero
+// we use the approximating forms derived in:
+// "Rational Approximations for the Modified Bessel Function of the First Kind – I1(x) for Computations with Double Precision"
+// by Pavel Holoborodko,
+// see http://www.advanpix.com/2015/11/12/rational-approximations-for-the-modified-bessel-function-of-the-first-kind-i1-for-computations-with-double-precision/
+// The actual coefficients used are our own, and extend Pavel's work to precision's other than double.
#ifndef BOOST_MATH_BESSEL_I1_HPP
#define BOOST_MATH_BESSEL_I1_HPP
@@ -21,21 +23,36 @@
namespace boost { namespace math { namespace detail{
template <typename T>
-T bessel_i1(T x);
+T bessel_i1(const T& x);
-template <class T>
+template <class T, class tag>
struct bessel_i1_initializer
{
struct init
{
init()
{
- do_init();
+ do_init(tag());
}
- static void do_init()
+ static void do_init(const mpl::int_<64>&)
{
bessel_i1(T(1));
+ bessel_i1(T(15));
+ bessel_i1(T(80));
+ bessel_i1(T(101));
}
+ static void do_init(const mpl::int_<113>&)
+ {
+ bessel_i1(T(1));
+ bessel_i1(T(10));
+ bessel_i1(T(14));
+ bessel_i1(T(19));
+ bessel_i1(T(34));
+ bessel_i1(T(99));
+ bessel_i1(T(101));
+ }
+ template <class U>
+ static void do_init(const U&) {}
void force_instantiate()const{}
};
static const init initializer;
@@ -45,86 +62,513 @@ struct bessel_i1_initializer
}
};
-template <class T>
-const typename bessel_i1_initializer<T>::init bessel_i1_initializer<T>::initializer;
+template <class T, class tag>
+const typename bessel_i1_initializer<T, tag>::init bessel_i1_initializer<T, tag>::initializer;
+
+template <typename T, int N>
+T bessel_i1_imp(const T&, const mpl::int_<N>&)
+{
+ BOOST_ASSERT(0);
+ return 0;
+}
+
+template <typename T>
+T bessel_i1_imp(const T& x, const mpl::int_<24>&)
+{
+ BOOST_MATH_STD_USING
+ if(x < 7.75)
+ {
+ //Max error in interpolated form : 1.348e-08
+ // Max Error found at float precision = Poly : 1.469121e-07
+ static const float P[] = {
+ 8.333333221e-02f,
+ 6.944453712e-03f,
+ 3.472097211e-04f,
+ 1.158047174e-05f,
+ 2.739745142e-07f,
+ 5.135884609e-09f,
+ 5.262251502e-11f,
+ 1.331933703e-12f
+ };
+ T a = x * x / 4;
+ T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
+ return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
+ }
+ else
+ {
+ // Max error in interpolated form: 9.000e-08
+ // Max Error found at float precision = Poly: 1.044345e-07
+
+ static const float P[] = {
+ 3.98942115977513013e-01f,
+ -1.49581264836620262e-01f,
+ -4.76475741878486795e-02f,
+ -2.65157315524784407e-02f,
+ -1.47148600683672014e-01f
+ };
+ T ex = exp(x / 2);
+ T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ result *= ex;
+ return result;
+ }
+}
+
+template <typename T>
+T bessel_i1_imp(const T& x, const mpl::int_<53>&)
+{
+ BOOST_MATH_STD_USING
+ if(x < 7.75)
+ {
+ // Bessel I0 over[10 ^ -16, 7.75]
+ // Max error in interpolated form: 5.639e-17
+ // Max Error found at double precision = Poly: 1.795559e-16
+
+ static const double P[] = {
+ 8.333333333333333803e-02,
+ 6.944444444444341983e-03,
+ 3.472222222225921045e-04,
+ 1.157407407354987232e-05,
+ 2.755731926254790268e-07,
+ 4.920949692800671435e-09,
+ 6.834657311305621830e-11,
+ 7.593969849687574339e-13,
+ 6.904822652741917551e-15,
+ 5.220157095351373194e-17,
+ 3.410720494727771276e-19,
+ 1.625212890947171108e-21,
+ 1.332898928162290861e-23
+ };
+ T a = x * x / 4;
+ T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
+ return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
+ }
+ else if(x < 500)
+ {
+ // Max error in interpolated form: 1.796e-16
+ // Max Error found at double precision = Poly: 2.898731e-16
+
+ static const double P[] = {
+ 3.989422804014406054e-01,
+ -1.496033551613111533e-01,
+ -4.675104253598537322e-02,
+ -4.090895951581637791e-02,
+ -5.719036414430205390e-02,
+ -1.528189554374492735e-01,
+ 3.458284470977172076e+00,
+ -2.426181371595021021e+02,
+ 1.178785865993440669e+04,
+ -4.404655582443487334e+05,
+ 1.277677779341446497e+07,
+ -2.903390398236656519e+08,
+ 5.192386898222206474e+09,
+ -7.313784438967834057e+10,
+ 8.087824484994859552e+11,
+ -6.967602516005787001e+12,
+ 4.614040809616582764e+13,
+ -2.298849639457172489e+14,
+ 8.325554073334618015e+14,
+ -2.067285045778906105e+15,
+ 3.146401654361325073e+15,
+ -2.213318202179221945e+15
+ };
+ return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ }
+ else
+ {
+ // Max error in interpolated form: 1.320e-19
+ // Max Error found at double precision = Poly: 7.065357e-17
+ static const double P[] = {
+ 3.989422804014314820e-01,
+ -1.496033551467584157e-01,
+ -4.675105322571775911e-02,
+ -4.090421597376992892e-02,
+ -5.843630344778927582e-02
+ };
+ T ex = exp(x / 2);
+ T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ result *= ex;
+ return result;
+ }
+}
+
+template <typename T>
+T bessel_i1_imp(const T& x, const mpl::int_<64>&)
+{
+ BOOST_MATH_STD_USING
+ if(x < 7.75)
+ {
+ // Bessel I0 over[10 ^ -16, 7.75]
+ // Max error in interpolated form: 8.086e-21
+ // Max Error found at float80 precision = Poly: 7.225090e-20
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 8.33333333333333333340071817e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 6.94444444444444442462728070e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.47222222222222318886683883e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.15740740740738880709555060e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.75573192240046222242685145e-07),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.92094986131253986838697503e-09),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 6.83465258979924922633502182e-11),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 7.59405830675154933645967137e-13),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 6.90369179710633344508897178e-15),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 5.23003610041709452814262671e-17),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.35291901027762552549170038e-19),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.83991379419781823063672109e-21),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 8.87732714140192556332037815e-24),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.32120654663773147206454247e-26),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.95294659305369207813486871e-28)
+ };
+ T a = x * x / 4;
+ T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
+ return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
+ }
+ else if(x < 20)
+ {
+ // Max error in interpolated form: 4.258e-20
+ // Max Error found at float80 precision = Poly: 2.851105e-19
+ // Maximum Deviation Found : 3.887e-20
+ // Expected Error Term : 3.887e-20
+ // Maximum Relative Change in Control Points : 1.681e-04
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942260530218897338680e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.49599542849073670179540e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.70492865454119188276875e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -3.12389893307392002405869e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.49696126385202602071197e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -3.84206507612717711565967e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.14748094784412558689584e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -7.70652726663596993005669e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.01659736164815617174439e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.04740659606466305607544e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 6.38383394696382837263656e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -8.00779638649147623107378e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 8.02338237858684714480491e+10),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -6.41198553664947312995879e+11),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.05915186909564986897554e+12),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -2.00907636964168581116181e+13),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 7.60855263982359981275199e+13),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -2.12901817219239205393806e+14),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.14861794397709807823575e+14),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -5.02808138522587680348583e+14),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.85505477056514919387171e+14)
+ };
+ return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ }
+ else if(x < 100)
+ {
+ // Bessel I0 over [15, 50]
+ // Maximum Deviation Found: 2.444e-20
+ // Expected Error Term : 2.438e-20
+ // Maximum Relative Change in Control Points : 2.101e-03
+ // Max Error found at float80 precision = Poly : 6.029974e-20
+
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401431675205845e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.49603355149968887210170e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.67510486284376330257260e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.09071458907089270559464e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -5.75278280327696940044714e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.10591299500956620739254e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -2.77061766699949309115618e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -5.42683771801837596371638e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -9.17021412070404158464316e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.04154379346763380543310e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.43462345357478348323006e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 9.98109660274422449523837e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -3.74438822767781410362757e+04)
+ };
+ return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ }
+ else
+ {
+ // Bessel I0 over[100, INF]
+ // Max error in interpolated form: 2.456e-20
+ // Max Error found at float80 precision = Poly: 5.446356e-20
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401432677958445e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.49603355150537411254359e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.67510484842456251368526e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.09071676503922479645155e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -5.75256179814881566010606e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.10754910257965227825040e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -2.67858639515616079840294e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -9.17266479586791298924367e-01)
+ };
+ T ex = exp(x / 2);
+ T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ result *= ex;
+ return result;
+ }
+}
+
+template <typename T>
+T bessel_i1_imp(const T& x, const mpl::int_<113>&)
+{
+ BOOST_MATH_STD_USING
+ if(x < 7.75)
+ {
+ // Bessel I0 over[10 ^ -34, 7.75]
+ // Max error in interpolated form: 1.835e-35
+ // Max Error found at float128 precision = Poly: 1.645036e-34
+
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.3333333333333333333333333333333331804098e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444444444444444444445418303082e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.4722222222222222222222222222119082346591e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.1574074074074074074074074078415867655987e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.7557319223985890652557318255143448192453e-07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.9209498614260519022423916850415000626427e-09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.8346525853139609753354247043900442393686e-11),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266233060080535940234144302217e-13),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.9036894801151120925605467963949641957095e-15),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.2300677879659941472662086395055636394839e-17),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.3526075563884539394691458717439115962233e-19),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.8420920639497841692288943167036233338434e-21),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.7718669711748690065381181691546032291365e-24),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.6549445715236427401845636880769861424730e-26),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.3437296196812697924703896979250126739676e-28),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.3912734588619073883015937023564978854893e-31),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.2839967682792395867255384448052781306897e-33),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.3790094235693528861015312806394354114982e-36),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.0423861671932104308662362292359563970482e-39),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.7493858979396446292135661268130281652945e-41),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.2786079392547776769387921361408303035537e-44),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.2335693685833531118863552173880047183822e-47)
+ };
+ T a = x * x / 4;
+ T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
+ return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
+ }
+ else if(x < 11)
+ {
+ // Max error in interpolated form: 8.574e-36
+ // Maximum Deviation Found : 4.689e-36
+ // Expected Error Term : 3.760e-36
+ // Maximum Relative Change in Control Points : 5.204e-03
+ // Max Error found at float128 precision = Poly : 2.882561e-34
+
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.333333333333333326889717360850080939e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.944444444444444511272790848815114507e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.472222222222221892451965054394153443e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.157407407407408437378868534321538798e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.755731922398566216824909767320161880e-07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.920949861426434829568192525456800388e-09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.834652585308926245465686943255486934e-11),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.594058428179852047689599244015979196e-13),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.903689479655006062822949671528763738e-15),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.230067791254403974475987777406992984e-17),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.352607536815161679702105115200693346e-19),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.842092161364672561828681848278567885e-21),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.771862912600611801856514076709932773e-24),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.654958704184380914803366733193713605e-26),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.343688672071130980471207297730607625e-28),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.392252844664709532905868749753463950e-31),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.282086786672692641959912811902298600e-33),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.408812012322547015191398229942864809e-36),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.681220437734066258673404589233009892e-39),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.072417451640733785626701738789290055e-41),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.352218520142636864158849446833681038e-44),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.407918492276267527897751358794783640e-46)
+ };
+ T a = x * x / 4;
+ T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
+ return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
+ }
+ else if(x < 15)
+ {
+ //Max error in interpolated form: 7.599e-36
+ // Maximum Deviation Found : 1.766e-35
+ // Expected Error Term : 1.021e-35
+ // Maximum Relative Change in Control Points : 6.228e-03
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.333333333333255774414858563409941233e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.944444444444897867884955912228700291e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.472222222220954970397343617150959467e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.157407407409660682751155024932538578e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.755731922369973706427272809014190998e-07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.920949861702265600960449699129258153e-09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.834652583208361401197752793379677147e-11),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.594058441128280500819776168239988143e-13),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.903689413939268702265479276217647209e-15),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.230068069012898202890718644753625569e-17),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.352606552027491657204243201021677257e-19),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.842095100698532984651921750204843362e-21),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.771789051329870174925649852681844169e-24),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.655114381199979536997025497438385062e-26),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.343415732516712339472538688374589373e-28),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.396177019032432392793591204647901390e-31),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.277563309255167951005939802771456315e-33),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.449201419305514579791370198046544736e-36),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.415430703400740634202379012388035255e-39),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.195458831864936225409005027914934499e-41),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.829726762743879793396637797534668039e-45),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.698302711685624490806751012380215488e-46),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.062520475425422618494185821587228317e-49),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.732372906742845717148185173723304360e-52)
+ };
+ T a = x * x / 4;
+ T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
+ return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
+ }
+ else if(x < 20)
+ {
+ // Max error in interpolated form: 8.864e-36
+ // Max Error found at float128 precision = Poly: 8.522841e-35
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422793693152031514179994954750043e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.496029423752889591425633234009799670e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.682975926820553021482820043377990241e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.138871171577224532369979905856458929e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -8.765350219426341341990447005798111212e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.321389275507714530941178258122955540e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.727748393898888756515271847678850411e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.123040820686242586086564998713862335e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.784112378374753535335272752884808068e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.054920416060932189433079126269416563e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.450129415468060676827180524327749553e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.758831882046487398739784498047935515e+10),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -7.736936520262204842199620784338052937e+11),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.051128683324042629513978256179115439e+13),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.188008285959794869092624343537262342e+14),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.108530004906954627420484180793165669e+15),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -8.441516828490144766650287123765318484e+15),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.158251664797753450664499268756393535e+16),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.467314522709016832128790443932896401e+17),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.896222045367960462945885220710294075e+17),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.273382139594876997203657902425653079e+18),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.669871448568623680543943144842394531e+18),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.813923031370708069940575240509912588e+18)
+ };
+ return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ }
+ else if(x < 35)
+ {
+ // Max error in interpolated form: 6.028e-35
+ // Max Error found at float128 precision = Poly: 1.368313e-34
+
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422804012941975429616956496046931e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.496033550576049830976679315420681402e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.675107835141866009896710750800622147e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.090104965125365961928716504473692957e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -5.842241652296980863361375208605487570e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.063604828033747303936724279018650633e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -9.113375972811586130949401996332817152e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.334748570425075872639817839399823709e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.759150758768733692594821032784124765e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.863672813448915255286274382558526321e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -7.798248643371718775489178767529282534e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.769963173932801026451013022000669267e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -8.381780137198278741566746511015220011e+10),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.163891337116820832871382141011952931e+12),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.764325864671438675151635117936912390e+13),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.925668307403332887856809510525154955e+14),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.416692606589060039334938090985713641e+16),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.892398600219306424294729851605944429e+17),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.107232903741874160308537145391245060e+18),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.930223393531877588898224144054112045e+19),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.427759576167665663373350433236061007e+20),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.306019279465532835530812122374386654e+20),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.653753000392125229440044977239174472e+21),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.140760686989511568435076842569804906e+22),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.249149337812510200795436107962504749e+22),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.101619088427348382058085685849420866e+22)
+ };
+ return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ }
+ else if(x < 100)
+ {
+ // Max error in interpolated form: 5.494e-35
+ // Max Error found at float128 precision = Poly: 1.214651e-34
+
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422804014326779399307367861631577e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.496033551505372542086590873271571919e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.675104848454290286276466276677172664e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.090716742397105403027549796269213215e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -5.752570419098513588311026680089351230e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.107369803696534592906420980901195808e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.699214194000085622941721628134575121e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -7.953006169077813678478720427604462133e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.746618809476524091493444128605380593e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.084446249943196826652788161656973391e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -5.020325182518980633783194648285500554e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.510195971266257573425196228564489134e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -5.241661863814900938075696173192225056e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.323374362891993686413568398575539777e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.112838452096066633754042734723911040e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.369270194978310081563767560113534023e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.704295412488936504389347368131134993e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.320829576277038198439987439508754886e+10),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.258818139077875493434420764260185306e+11),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.396791306321498426110315039064592443e+12),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.217617301585849875301440316301068439e+12)
+ };
+ return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ }
+ else
+ {
+ // Bessel I0 over[100, INF]
+ // Max error in interpolated form: 6.081e-35
+ // Max Error found at float128 precision = Poly: 1.407151e-34
+ static const T P[] = {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793994605993438200208417e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.4960335515053725422747977247811372936584e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.6751048484542891946087411826356811991039e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.0907167423975030452875828826630006305665e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -5.7525704189964886494791082898669060345483e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.1073698056568248642163476807108190176386e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.6992139012879749064623499618582631684228e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -7.9530409594026597988098934027440110587905e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.7462844478733532517044536719240098183686e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.0870711340681926669381449306654104739256e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.8510175413216969245241059608553222505228e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.4094682286011573747064907919522894740063e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.3128845936764406865199641778959502795443e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -8.1655901321962541203257516341266838487359e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.8019591025686295090160445920753823994556e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -6.7008089049178178697338128837158732831105e+05)
+ };
+ T ex = exp(x / 2);
+ T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
+ result *= ex;
+ return result;
+ }
+}
+
+template <typename T>
+T bessel_i1_imp(const T& x, const mpl::int_<0>&)
+{
+ if(boost::math::tools::digits<T>() <= 24)
+ return bessel_i1_imp(x, mpl::int_<24>());
+ else if(boost::math::tools::digits<T>() <= 53)
+ return bessel_i1_imp(x, mpl::int_<53>());
+ else if(boost::math::tools::digits<T>() <= 64)
+ return bessel_i1_imp(x, mpl::int_<64>());
+ else if(boost::math::tools::digits<T>() <= 113)
+ return bessel_i1_imp(x, mpl::int_<113>());
+ BOOST_ASSERT(0);
+ return 0;
+}
template <typename T>
-T bessel_i1(T x)
+inline T bessel_i1(const T& x)
{
+ typedef mpl::int_<
+ std::numeric_limits<T>::digits == 0 ?
+ 0 :
+ std::numeric_limits<T>::digits <= 24 ?
+ 24 :
+ std::numeric_limits<T>::digits <= 53 ?
+ 53 :
+ std::numeric_limits<T>::digits <= 64 ?
+ 64 :
+ std::numeric_limits<T>::digits <= 113 ?
+ 113 : -1
+ > tag_type;
- bessel_i1_initializer<T>::force_instantiate();
-
- static const T P1[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4577180278143463643e+15)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.7732037840791591320e+14)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.9876779648010090070e+12)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.3357437682275493024e+11)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4828267606612366099e+09)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.0588550724769347106e+07)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.1894091982308017540e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8225946631657315931e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.7207090827310162436e-01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -9.1746443287817501309e-04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.3466829827635152875e-06)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4831904935994647675e-09)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.1928788903603238754e-12)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.5245515583151902910e-16)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.9705291802535139930e-19)),
- };
- static const T Q1[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.9154360556286927285e+15)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.7887501377547640438e+12)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4386907088588283434e+10)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1594225856856884006e+07)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.1326864679904189920e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
- };
- static const T P2[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4582087408985668208e-05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.9359825138577646443e-04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.9204895411257790122e-02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.4198728018058047439e-01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3960118277609544334e+00)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.9746376087200685843e+00)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.5591872901933459000e-01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.0437159056137599999e-02)),
- };
- static const T Q2[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.7510433111922824643e-05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2835624489492512649e-03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.4212010813186530069e-02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.5017476463217924408e-01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.2593714889036996297e+00)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.8806586721556593450e+00)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
- };
- T value, factor, r, w;
-
- BOOST_MATH_STD_USING
- using namespace boost::math::tools;
-
- BOOST_ASSERT(x >= 0); // negative x is handled before we get here
- w = abs(x);
- if (x == 0)
- {
- return static_cast<T>(0);
- }
- if (w <= 15) // w in (0, 15]
- {
- T y = x * x;
- r = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
- factor = w;
- value = factor * r;
- }
- else // w in (15, \infty)
- {
- T y = 1 / w - T(1) / 15;
- r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
- factor = exp(w) / sqrt(w);
- value = factor * r;
- }
-
- return value;
+ bessel_i1_initializer<T, tag_type>::force_instantiate();
+ return bessel_i1_imp(x, tag_type());
}
}}} // namespaces
diff --git a/boost/math/special_functions/detail/bessel_k0.hpp b/boost/math/special_functions/detail/bessel_k0.hpp
index 42041dc673..4f3420ffc0 100644
--- a/boost/math/special_functions/detail/bessel_k0.hpp
+++ b/boost/math/special_functions/detail/bessel_k0.hpp
@@ -1,4 +1,5 @@
// Copyright (c) 2006 Xiaogang Zhang
+// Copyright (c) 2017 John Maddock
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -19,26 +20,43 @@
// Modified Bessel function of the second kind of order zero
// minimax rational approximations on intervals, see
-// Russon and Blair, Chalk River Report AECL-3461, 1969
+// Russon and Blair, Chalk River Report AECL-3461, 1969,
+// as revised by Pavel Holoborodko in "Rational Approximations
+// for the Modified Bessel Function of the Second Kind - K0(x)
+// for Computations with Double Precision", see
+// http://www.advanpix.com/2015/11/25/rational-approximations-for-the-modified-bessel-function-of-the-second-kind-k0-for-computations-with-double-precision/
+//
+// The actual coefficients used are our own derivation (by JM)
+// since we extend to both greater and lesser precision than the
+// references above. We can also improve performance WRT to
+// Holoborodko without loss of precision.
namespace boost { namespace math { namespace detail{
-template <typename T, typename Policy>
-T bessel_k0(T x, const Policy&);
+template <typename T>
+T bessel_k0(const T& x);
-template <class T, class Policy>
+template <class T, class tag>
struct bessel_k0_initializer
{
struct init
{
init()
{
- do_init();
+ do_init(tag());
}
- static void do_init()
+ static void do_init(const mpl::int_<113>&)
{
- bessel_k0(T(1), Policy());
+ bessel_k0(T(0.5));
+ bessel_k0(T(1.5));
}
+ static void do_init(const mpl::int_<64>&)
+ {
+ bessel_k0(T(0.5));
+ bessel_k0(T(1.5));
+ }
+ template <class U>
+ static void do_init(const U&){}
void force_instantiate()const{}
};
static const init initializer;
@@ -48,104 +66,437 @@ struct bessel_k0_initializer
}
};
-template <class T, class Policy>
-const typename bessel_k0_initializer<T, Policy>::init bessel_k0_initializer<T, Policy>::initializer;
+template <class T, class tag>
+const typename bessel_k0_initializer<T, tag>::init bessel_k0_initializer<T, tag>::initializer;
+
+
+template <typename T, int N>
+T bessel_k0_imp(const T& x, const mpl::int_<N>&)
+{
+ BOOST_ASSERT(0);
+ return 0;
+}
+
+template <typename T>
+T bessel_k0_imp(const T& x, const mpl::int_<24>&)
+{
+ BOOST_MATH_STD_USING
+ if(x <= 1)
+ {
+ // Maximum Deviation Found : 2.358e-09
+ // Expected Error Term : -2.358e-09
+ // Maximum Relative Change in Control Points : 9.552e-02
+ // Max Error found at float precision = Poly : 4.448220e-08
+ static const T Y = 1.137250900268554688f;
+ static const T P[] =
+ {
+ -1.372508979104259711e-01f,
+ 2.622545986273687617e-01f,
+ 5.047103728247919836e-03f
+ };
+ static const T Q[] =
+ {
+ 1.000000000000000000e+00f,
+ -8.928694018000029415e-02f,
+ 2.985980684180969241e-03f
+ };
+ T a = x * x / 4;
+ a = (tools::evaluate_rational(P, Q, a) + Y) * a + 1;
+
+ // Maximum Deviation Found: 1.346e-09
+ // Expected Error Term : -1.343e-09
+ // Maximum Relative Change in Control Points : 2.405e-02
+ // Max Error found at float precision = Poly : 1.354814e-07
+ static const T P2[] = {
+ 1.159315158e-01f,
+ 2.789828686e-01f,
+ 2.524902861e-02f,
+ 8.457241514e-04f,
+ 1.530051997e-05f
+ };
+ return tools::evaluate_polynomial(P2, T(x * x)) - log(x) * a;
+ }
+ else
+ {
+ // Maximum Deviation Found: 1.587e-08
+ // Expected Error Term : 1.531e-08
+ // Maximum Relative Change in Control Points : 9.064e-02
+ // Max Error found at float precision = Poly : 5.065020e-08
+
+ static const T P[] =
+ {
+ 2.533141220e-01,
+ 5.221502603e-01,
+ 6.380180669e-02,
+ -5.934976547e-02
+ };
+ static const T Q[] =
+ {
+ 1.000000000e+00,
+ 2.679722431e+00,
+ 1.561635813e+00,
+ 1.573660661e-01
+ };
+ if(x < tools::log_max_value<T>())
+ return ((tools::evaluate_rational(P, Q, T(1 / x)) + 1) * exp(-x) / sqrt(x));
+ else
+ {
+ T ex = exp(-x / 2);
+ return ((tools::evaluate_rational(P, Q, T(1 / x)) + 1) * ex / sqrt(x)) * ex;
+ }
+ }
+}
+
+template <typename T>
+T bessel_k0_imp(const T& x, const mpl::int_<53>&)
+{
+ BOOST_MATH_STD_USING
+ if(x <= 1)
+ {
+ // Maximum Deviation Found: 6.077e-17
+ // Expected Error Term : -6.077e-17
+ // Maximum Relative Change in Control Points : 7.797e-02
+ // Max Error found at double precision = Poly : 1.003156e-16
+ static const T Y = 1.137250900268554688;
+ static const T P[] =
+ {
+ -1.372509002685546267e-01,
+ 2.574916117833312855e-01,
+ 1.395474602146869316e-02,
+ 5.445476986653926759e-04,
+ 7.125159422136622118e-06
+ };
+ static const T Q[] =
+ {
+ 1.000000000000000000e+00,
+ -5.458333438017788530e-02,
+ 1.291052816975251298e-03,
+ -1.367653946978586591e-05
+ };
+
+ T a = x * x / 4;
+ a = (tools::evaluate_polynomial(P, a) / tools::evaluate_polynomial(Q, a) + Y) * a + 1;
+
+ // Maximum Deviation Found: 3.429e-18
+ // Expected Error Term : 3.392e-18
+ // Maximum Relative Change in Control Points : 2.041e-02
+ // Max Error found at double precision = Poly : 2.513112e-16
+ static const T P2[] =
+ {
+ 1.159315156584124484e-01,
+ 2.789828789146031732e-01,
+ 2.524892993216121934e-02,
+ 8.460350907213637784e-04,
+ 1.491471924309617534e-05,
+ 1.627106892422088488e-07,
+ 1.208266102392756055e-09,
+ 6.611686391749704310e-12
+ };
+
+ return tools::evaluate_polynomial(P2, T(x * x)) - log(x) * a;
+ }
+ else
+ {
+ // Maximum Deviation Found: 4.316e-17
+ // Expected Error Term : 9.570e-18
+ // Maximum Relative Change in Control Points : 2.757e-01
+ // Max Error found at double precision = Poly : 1.001560e-16
+
+ static const T Y = 1;
+ static const T P[] =
+ {
+ 2.533141373155002416e-01,
+ 3.628342133984595192e+00,
+ 1.868441889406606057e+01,
+ 4.306243981063412784e+01,
+ 4.424116209627428189e+01,
+ 1.562095339356220468e+01,
+ -1.810138978229410898e+00,
+ -1.414237994269995877e+00,
+ -9.369168119754924625e-02
+ };
+ static const T Q[] =
+ {
+ 1.000000000000000000e+00,
+ 1.494194694879908328e+01,
+ 8.265296455388554217e+01,
+ 2.162779506621866970e+02,
+ 2.845145155184222157e+02,
+ 1.851714491916334995e+02,
+ 5.486540717439723515e+01,
+ 6.118075837628957015e+00,
+ 1.586261269326235053e-01
+ };
+ if(x < tools::log_max_value<T>())
+ return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
+ else
+ {
+ T ex = exp(-x / 2);
+ return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
+ }
+ }
+}
-template <typename T, typename Policy>
-T bessel_k0(T x, const Policy& pol)
+template <typename T>
+T bessel_k0_imp(const T& x, const mpl::int_<64>&)
{
- BOOST_MATH_INSTRUMENT_CODE(x);
-
- bessel_k0_initializer<T, Policy>::force_instantiate();
-
- static const T P1[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.4708152720399552679e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.9169059852270512312e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.6850901201934832188e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1999463724910714109e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3166052564989571850e-01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.8599221412826100000e-04))
- };
- static const T Q1[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1312714303849120380e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.4994418972832303646e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
- };
- static const T P2[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.6128136304458193998e+06)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.7333769444840079748e+05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.7984434409411765813e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.9501657892958843865e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.6414452837299064100e+00))
- };
- static const T Q2[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.6128136304458193998e+06)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.9865713163054025489e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.5064972445877992730e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
- };
- static const T P3[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1600249425076035558e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.3444738764199315021e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8321525870183537725e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.1557062783764037541e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.5097646353289914539e+05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7398867902565686251e+05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0577068948034021957e+05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.1075408980684392399e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.6832589957340267940e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1394980557384778174e+02))
- };
- static const T Q3[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.2556599177304839811e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8821890840982713696e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4847228371802360957e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.8824616785857027752e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.2689839587977598727e+05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.5144644673520157801e+05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.7418829762268075784e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.1474655750295278825e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.4329628889746408858e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.0013443064949242491e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
- };
- T value, factor, r, r1, r2;
-
- BOOST_MATH_STD_USING
- using namespace boost::math::tools;
-
- static const char* function = "boost::math::bessel_k0<%1%>(%1%,%1%)";
-
- if (x < 0)
- {
- return policies::raise_domain_error<T>(function,
- "Got x = %1%, but argument x must be non-negative, complex number result not supported", x, pol);
- }
- if (x == 0)
- {
- return policies::raise_overflow_error<T>(function, 0, pol);
- }
- if (x <= 1) // x in (0, 1]
- {
- T y = x * x;
- r1 = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
- r2 = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
- factor = log(x);
- value = r1 - factor * r2;
- }
- else // x in (1, \infty)
- {
- T y = 1 / x;
- r = evaluate_polynomial(P3, y) / evaluate_polynomial(Q3, y);
- factor = exp(-x) / sqrt(x);
- value = factor * r;
- BOOST_MATH_INSTRUMENT_CODE("y = " << y);
- BOOST_MATH_INSTRUMENT_CODE("r = " << r);
- BOOST_MATH_INSTRUMENT_CODE("factor = " << factor);
- BOOST_MATH_INSTRUMENT_CODE("value = " << value);
- }
-
- return value;
+ BOOST_MATH_STD_USING
+ if(x <= 1)
+ {
+ // Maximum Deviation Found: 2.180e-22
+ // Expected Error Term : 2.180e-22
+ // Maximum Relative Change in Control Points : 2.943e-01
+ // Max Error found at float80 precision = Poly : 3.923207e-20
+ static const T Y = 1.137250900268554687500e+00;
+ static const T P[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.372509002685546875002e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.566481981037407600436e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.551881122448948854873e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 6.646112454323276529650e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.213747930378196492543e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 9.423709328020389560844e-08)
+ };
+ static const T Q[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.843828412587773008342e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.088484822515098936140e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.374724008530702784829e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 8.452665455952581680339e-08)
+ };
+
+
+ T a = x * x / 4;
+ a = (tools::evaluate_polynomial(P, a) / tools::evaluate_polynomial(Q, a) + Y) * a + 1;
+
+ // Maximum Deviation Found: 2.440e-21
+ // Expected Error Term : -2.434e-21
+ // Maximum Relative Change in Control Points : 2.459e-02
+ // Max Error found at float80 precision = Poly : 1.482487e-19
+ static const T P2[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.159315156584124488110e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.764832791416047889734e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.926062887220923354112e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.660777862036966089410e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.094942446930673386849e-06)
+ };
+ static const T Q2[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -2.156100313881251616320e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.315993873344905957033e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.529444499350703363451e-06),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 5.524988589917857531177e-09)
+ };
+ return tools::evaluate_rational(P2, Q2, T(x * x)) - log(x) * a;
+ }
+ else
+ {
+ // Maximum Deviation Found: 4.291e-20
+ // Expected Error Term : 2.236e-21
+ // Maximum Relative Change in Control Points : 3.021e-01
+ //Max Error found at float80 precision = Poly : 8.727378e-20
+ static const T Y = 1;
+ static const T P[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.533141373155002512056e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 5.417942070721928652715e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.477464607463971754433e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.838745728725943889876e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.009736314927811202517e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.557411293123609803452e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.360222564015361268955e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.385435333168505701022e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.750195760942181592050e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.059789241612946683713e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.612783121537333908889e-01)
+ };
+ static const T Q[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.200669254769325861404e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.900177593527144126549e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 8.361003989965786932682e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.041319870804843395893e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.828491555113790345068e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.190342229261529076624e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 9.003330795963812219852e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.773371397243777891569e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.368634935531158398439e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.543310879400359967327e-01)
+ };
+ if(x < tools::log_max_value<T>())
+ return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
+ else
+ {
+ T ex = exp(-x / 2);
+ return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
+ }
+ }
+}
+
+template <typename T>
+T bessel_k0_imp(const T& x, const mpl::int_<113>&)
+{
+ BOOST_MATH_STD_USING
+ if(x <= 1)
+ {
+ // Maximum Deviation Found: 5.682e-37
+ // Expected Error Term : 5.682e-37
+ // Maximum Relative Change in Control Points : 6.094e-04
+ // Max Error found at float128 precision = Poly : 5.338213e-35
+ static const T Y = 1.137250900268554687500000000000000000e+00f;
+ static const T P[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.372509002685546875000000000000000006e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.556212905071072782462974351698081303e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.742459135264203478530904179889103929e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.077860530453688571555479526961318918e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.868173911669241091399374307788635148e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.496405768838992243478709145123306602e-07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.752489221949580551692915881999762125e-09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.243010555737173524710512824955368526e-12)
+ };
+ static const T Q[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.095631064064621099785696980653193721e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.313880983725212151967078809725835532e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.095229912293480063501285562382835142e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.022828799511943141130509410251996277e-07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -6.860874007419812445494782795829046836e-10),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.107297802344970725756092082686799037e-12),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -7.460529579244623559164763757787600944e-15)
+ };
+ T a = x * x / 4;
+ a = (tools::evaluate_rational(P, Q, a) + Y) * a + 1;
+
+ // Maximum Deviation Found: 5.173e-38
+ // Expected Error Term : 5.105e-38
+ // Maximum Relative Change in Control Points : 9.734e-03
+ // Max Error found at float128 precision = Poly : 1.688806e-34
+ static const T P2[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.159315156584124488107200313757741370e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.789828789146031122026800078439435369e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.524892993216269451266750049024628432e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.460350907082229957222453839935101823e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.491471929926042875260452849503857976e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.627105610481598430816014719558896866e-07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.208426165007797264194914898538250281e-09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.508697838747354949164182457073784117e-12),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.659784680639805301101014383907273109e-14),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.531090131964391104248859415958109654e-17),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.205195117066478034260323124669936314e-19),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.692219280289030165761119775783115426e-22),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.362350161092532344171965861545860747e-25),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.277990623924628999539014980773738258e-27)
+ };
+
+ return tools::evaluate_polynomial(P2, T(x * x)) - log(x) * a;
+ }
+ else
+ {
+ // Maximum Deviation Found: 1.462e-34
+ // Expected Error Term : 4.917e-40
+ // Maximum Relative Change in Control Points : 3.385e-01
+ // Max Error found at float128 precision = Poly : 1.567573e-34
+ static const T Y = 1;
+ static const T P[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.533141373155002512078826424055226265e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.001949740768235770078339977110749204e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.991516715983883248363351472378349986e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.429587951594593159075690819360687720e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.911933815201948768044660065771258450e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.769943016204926614862175317962439875e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.170866154649560750500954150401105606e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.634687099724383996792011977705727661e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.989524036456492581597607246664394014e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.160394785715328062088529400178080360e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.778173054417826368076483100902201433e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.335667778588806892764139643950439733e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.283635100080306980206494425043706838e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.300616188213640626577036321085025855e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.277591957076162984986406540894621482e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.564360536834214058158565361486115932e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.043505161612403359098596828115690596e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -7.217035248223503605127967970903027314e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.422938158797326748375799596769964430e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.229125746200586805278634786674745210e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.201632288615609937883545928660649813e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.690820607338480548346746717311811406e+01)
+ };
+ static const T Q[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.964877874035741452203497983642653107e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.808929943826193766839360018583294769e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.814524004679994110944366890912384139e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.897794522506725610540209610337355118e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.456339470955813675629523617440433672e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.057818717813969772198911392875127212e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.513821619536852436424913886081133209e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.255938846873380596038513316919990776e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.537077551699028079347581816919572141e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.176769339768120752974843214652367321e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.828722317390455845253191337207432060e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.698864296569996402006511705803675890e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.007803261356636409943826918468544629e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.016564631288740308993071395104715469e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.595893010619754750655947035567624730e+09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.241241839120481076862742189989406856e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.168778094393076220871007550235840858e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.156200301360388147635052029404211109e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.752130382550379886741949463587008794e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.370574966987293592457152146806662562e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.871254714311063594080644835895740323e+01)
+ };
+ if(x < tools::log_max_value<T>())
+ return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
+ else
+ {
+ T ex = exp(-x / 2);
+ return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
+ }
+ }
+}
+
+template <typename T>
+T bessel_k0_imp(const T& x, const mpl::int_<0>&)
+{
+ if(boost::math::tools::digits<T>() <= 24)
+ return bessel_k0_imp(x, mpl::int_<24>());
+ else if(boost::math::tools::digits<T>() <= 53)
+ return bessel_k0_imp(x, mpl::int_<53>());
+ else if(boost::math::tools::digits<T>() <= 64)
+ return bessel_k0_imp(x, mpl::int_<64>());
+ else if(boost::math::tools::digits<T>() <= 113)
+ return bessel_k0_imp(x, mpl::int_<113>());
+ BOOST_ASSERT(0);
+ return 0;
+}
+
+template <typename T>
+inline T bessel_k0(const T& x)
+{
+ typedef mpl::int_<
+ std::numeric_limits<T>::digits == 0 ?
+ 0 :
+ std::numeric_limits<T>::digits <= 24 ?
+ 24 :
+ std::numeric_limits<T>::digits <= 53 ?
+ 53 :
+ std::numeric_limits<T>::digits <= 64 ?
+ 64 :
+ std::numeric_limits<T>::digits <= 113 ?
+ 113 : -1
+ > tag_type;
+
+ bessel_k0_initializer<T, tag_type>::force_instantiate();
+ return bessel_k0_imp(x, tag_type());
}
}}} // namespaces
diff --git a/boost/math/special_functions/detail/bessel_k1.hpp b/boost/math/special_functions/detail/bessel_k1.hpp
index c0c5478520..0ae90056cb 100644
--- a/boost/math/special_functions/detail/bessel_k1.hpp
+++ b/boost/math/special_functions/detail/bessel_k1.hpp
@@ -1,4 +1,5 @@
// Copyright (c) 2006 Xiaogang Zhang
+// Copyright (c) 2017 John Maddock
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -17,132 +18,528 @@
#include <boost/math/policies/error_handling.hpp>
#include <boost/assert.hpp>
-// Modified Bessel function of the second kind of order one
+// Modified Bessel function of the second kind of order zero
// minimax rational approximations on intervals, see
-// Russon and Blair, Chalk River Report AECL-3461, 1969
+// Russon and Blair, Chalk River Report AECL-3461, 1969,
+// as revised by Pavel Holoborodko in "Rational Approximations
+// for the Modified Bessel Function of the Second Kind - K0(x)
+// for Computations with Double Precision", see
+// http://www.advanpix.com/2016/01/05/rational-approximations-for-the-modified-bessel-function-of-the-second-kind-k1-for-computations-with-double-precision/
+//
+// The actual coefficients used are our own derivation (by JM)
+// since we extend to both greater and lesser precision than the
+// references above. We can also improve performance WRT to
+// Holoborodko without loss of precision.
namespace boost { namespace math { namespace detail{
-template <typename T, typename Policy>
-T bessel_k1(T x, const Policy&);
+ template <typename T>
+ T bessel_k1(const T& x);
-template <class T, class Policy>
-struct bessel_k1_initializer
-{
- struct init
+ template <class T, class tag>
+ struct bessel_k1_initializer
{
- init()
+ struct init
{
- do_init();
- }
- static void do_init()
+ init()
+ {
+ do_init(tag());
+ }
+ static void do_init(const mpl::int_<113>&)
+ {
+ bessel_k1(T(0.5));
+ bessel_k1(T(2));
+ bessel_k1(T(6));
+ }
+ static void do_init(const mpl::int_<64>&)
+ {
+ bessel_k1(T(0.5));
+ bessel_k1(T(6));
+ }
+ template <class U>
+ static void do_init(const U&) {}
+ void force_instantiate()const {}
+ };
+ static const init initializer;
+ static void force_instantiate()
{
- bessel_k1(T(1), Policy());
+ initializer.force_instantiate();
}
- void force_instantiate()const{}
};
- static const init initializer;
- static void force_instantiate()
+
+ template <class T, class tag>
+ const typename bessel_k1_initializer<T, tag>::init bessel_k1_initializer<T, tag>::initializer;
+
+
+ template <typename T, int N>
+ inline T bessel_k1_imp(const T& x, const mpl::int_<N>&)
{
- initializer.force_instantiate();
+ BOOST_ASSERT(0);
+ return 0;
}
-};
-
-template <class T, class Policy>
-const typename bessel_k1_initializer<T, Policy>::init bessel_k1_initializer<T, Policy>::initializer;
-
-template <typename T, typename Policy>
-T bessel_k1(T x, const Policy& pol)
-{
- bessel_k1_initializer<T, Policy>::force_instantiate();
-
- static const T P1[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2149374878243304548e+06)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.1938920065420586101e+05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7733324035147015630e+05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.1885382604084798576e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.9991373567429309922e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.8127070456878442310e-01))
- };
- static const T Q1[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2149374878243304548e+06)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.7264298672067697862e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.8143915754538725829e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
- };
- static const T P2[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.3531161492785421328e+06)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.4758069205414222471e+05)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.5051623763436087023e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -5.3103913335180275253e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2795590826955002390e-01))
- };
- static const T Q2[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.7062322985570842656e+06)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.3117653211351080007e+04)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.0507151578787595807e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
- };
- static const T P3[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2196792496874548962e+00)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.4137176114230414036e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.4122953486801312910e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3319486433183221990e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.8590657697910288226e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.4540675585544584407e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.3123742209168871550e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.1094256146537402173e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3182609918569941308e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.5584584631176030810e+00)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.4257745859173138767e-02))
- };
- static const T Q3[] = {
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.7710478032601086579e+00)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.4552228452758912848e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.5951223655579051357e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.6929165726802648634e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.9448440788918006154e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1181000487171943810e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.2082692316002348638e+03)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.3031020088765390854e+02)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.6001069306861518855e+01)),
- static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
- };
- T value, factor, r, r1, r2;
-
- BOOST_MATH_STD_USING
- using namespace boost::math::tools;
-
- static const char* function = "boost::math::bessel_k1<%1%>(%1%,%1%)";
-
- if (x < 0)
- {
- return policies::raise_domain_error<T>(function,
- "Got x = %1%, but argument x must be non-negative, complex number result not supported.", x, pol);
- }
- if (x == 0)
- {
- return policies::raise_overflow_error<T>(function, 0, pol);
- }
- if (x <= 1) // x in (0, 1]
- {
- T y = x * x;
- r1 = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
- r2 = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
- factor = log(x);
- value = (r1 + factor * r2) / x;
+
+ template <typename T>
+ T bessel_k1_imp(const T& x, const mpl::int_<24>&)
+ {
+ BOOST_MATH_STD_USING
+ if(x <= 1)
+ {
+ // Maximum Deviation Found: 3.090e-12
+ // Expected Error Term : -3.053e-12
+ // Maximum Relative Change in Control Points : 4.927e-02
+ // Max Error found at float precision = Poly : 7.918347e-10
+ static const T Y = 8.695471287e-02f;
+ static const T P[] =
+ {
+ -3.621379531e-03f,
+ 7.131781976e-03f,
+ -1.535278300e-05f
+ };
+ static const T Q[] =
+ {
+ 1.000000000e+00f,
+ -5.173102701e-02f,
+ 9.203530671e-04f
+ };
+
+ T a = x * x / 4;
+ a = ((tools::evaluate_rational(P, Q, a) + Y) * a * a + a / 2 + 1) * x / 2;
+
+ // Maximum Deviation Found: 3.556e-08
+ // Expected Error Term : -3.541e-08
+ // Maximum Relative Change in Control Points : 8.203e-02
+ static const T P2[] =
+ {
+ -3.079657469e-01f,
+ -8.537108913e-02f,
+ -4.640275408e-03f,
+ -1.156442414e-04f
+ };
+
+ return tools::evaluate_polynomial(P2, T(x * x)) * x + 1 / x + log(x) * a;
+ }
+ else
+ {
+ // Maximum Deviation Found: 3.369e-08
+ // Expected Error Term : -3.227e-08
+ // Maximum Relative Change in Control Points : 9.917e-02
+ // Max Error found at float precision = Poly : 6.084411e-08
+ static const T Y = 1.450342178f;
+ static const T P[] =
+ {
+ -1.970280088e-01f,
+ 2.188747807e-02f,
+ 7.270394756e-01f,
+ 2.490678196e-01f
+ };
+ static const T Q[] =
+ {
+ 1.000000000e+00f,
+ 2.274292882e+00f,
+ 9.904984851e-01f,
+ 4.585534549e-02f
+ };
+ if(x < tools::log_max_value<T>())
+ return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
+ else
+ {
+ T ex = exp(-x / 2);
+ return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
+ }
+ }
+ }
+
+ template <typename T>
+ T bessel_k1_imp(const T& x, const mpl::int_<53>&)
+ {
+ BOOST_MATH_STD_USING
+ if(x <= 1)
+ {
+ // Maximum Deviation Found: 1.922e-17
+ // Expected Error Term : 1.921e-17
+ // Maximum Relative Change in Control Points : 5.287e-03
+ // Max Error found at double precision = Poly : 2.004747e-17
+ static const T Y = 8.69547128677368164e-02f;
+ static const T P[] =
+ {
+ -3.62137953440350228e-03,
+ 7.11842087490330300e-03,
+ 1.00302560256614306e-05,
+ 1.77231085381040811e-06
+ };
+ static const T Q[] =
+ {
+ 1.00000000000000000e+00,
+ -4.80414794429043831e-02,
+ 9.85972641934416525e-04,
+ -8.91196859397070326e-06
+ };
+
+ T a = x * x / 4;
+ a = ((tools::evaluate_rational(P, Q, a) + Y) * a * a + a / 2 + 1) * x / 2;
+
+ // Maximum Deviation Found: 4.053e-17
+ // Expected Error Term : -4.053e-17
+ // Maximum Relative Change in Control Points : 3.103e-04
+ // Max Error found at double precision = Poly : 1.246698e-16
+
+ static const T P2[] =
+ {
+ -3.07965757829206184e-01,
+ -7.80929703673074907e-02,
+ -2.70619343754051620e-03,
+ -2.49549522229072008e-05
+ };
+ static const T Q2[] =
+ {
+ 1.00000000000000000e+00,
+ -2.36316836412163098e-02,
+ 2.64524577525962719e-04,
+ -1.49749618004162787e-06
+ };
+
+ return tools::evaluate_rational(P2, Q2, T(x * x)) * x + 1 / x + log(x) * a;
+ }
+ else
+ {
+ // Maximum Deviation Found: 8.883e-17
+ // Expected Error Term : -1.641e-17
+ // Maximum Relative Change in Control Points : 2.786e-01
+ // Max Error found at double precision = Poly : 1.258798e-16
+
+ static const T Y = 1.45034217834472656f;
+ static const T P[] =
+ {
+ -1.97028041029226295e-01,
+ -2.32408961548087617e+00,
+ -7.98269784507699938e+00,
+ -2.39968410774221632e+00,
+ 3.28314043780858713e+01,
+ 5.67713761158496058e+01,
+ 3.30907788466509823e+01,
+ 6.62582288933739787e+00,
+ 3.08851840645286691e-01
+ };
+ static const T Q[] =
+ {
+ 1.00000000000000000e+00,
+ 1.41811409298826118e+01,
+ 7.35979466317556420e+01,
+ 1.77821793937080859e+02,
+ 2.11014501598705982e+02,
+ 1.19425262951064454e+02,
+ 2.88448064302447607e+01,
+ 2.27912927104139732e+00,
+ 2.50358186953478678e-02
+ };
+ if(x < tools::log_max_value<T>())
+ return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
+ else
+ {
+ T ex = exp(-x / 2);
+ return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
+ }
+ }
+ }
+
+ template <typename T>
+ T bessel_k1_imp(const T& x, const mpl::int_<64>&)
+ {
+ BOOST_MATH_STD_USING
+ if(x <= 1)
+ {
+ // Maximum Deviation Found: 5.549e-23
+ // Expected Error Term : -5.548e-23
+ // Maximum Relative Change in Control Points : 2.002e-03
+ // Max Error found at float80 precision = Poly : 9.352785e-22
+ static const T Y = 8.695471286773681640625e-02f;
+ static const T P[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 64, -3.621379534403483072861e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 7.102135866103952705932e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.167545240236717601167e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.537484002571894870830e-06),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 6.603228256820000135990e-09)
+ };
+ static const T Q[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.354457194045068370363e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 8.709137201220209072820e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -9.676151796359590545143e-06),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 5.162715192766245311659e-08)
+ };
+
+ T a = x * x / 4;
+ a = ((tools::evaluate_rational(P, Q, a) + Y) * a * a + a / 2 + 1) * x / 2;
+
+ // Maximum Deviation Found: 1.995e-23
+ // Expected Error Term : 1.995e-23
+ // Maximum Relative Change in Control Points : 8.174e-04
+ // Max Error found at float80 precision = Poly : 4.137325e-20
+ static const T P2[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 64, -3.079657578292062244054e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -7.963049154965966503231e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -3.103277523735639924895e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.023052834702215699504e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.719459155018493821839e-07)
+ };
+ static const T Q2[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.863917670410152669768e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.699367098849735298090e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -9.309358790546076298429e-07),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.708893480271612711933e-09)
+ };
+
+ return tools::evaluate_rational(P2, Q2, T(x * x)) * x + 1 / x + log(x) * a;
+ }
+ else
+ {
+ // Maximum Deviation Found: 9.785e-20
+ // Expected Error Term : -3.302e-21
+ // Maximum Relative Change in Control Points : 3.432e-01
+ // Max Error found at float80 precision = Poly : 1.083755e-19
+ static const T Y = 1.450342178344726562500e+00f;
+ static const T P[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 64, -1.970280410292263112917e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -4.058564803062959169322e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -3.036658174194917777473e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -9.576825392332820142173e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, -6.706969489248020941949e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.264572499406168221382e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 8.584972047303151034100e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 8.422082733280017909550e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.738005441471368178383e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 7.016938390144121276609e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 4.319614662598089438939e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.710715864316521856193e-02)
+ };
+ static const T Q[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.298433045824439052398e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.082047745067709230037e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 9.662367854250262046592e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.504148628460454004686e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.712730364911389908905e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.108002081150068641112e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 1.400149940532448553143e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 3.083303048095846226299e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 2.748706060530351833346e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 64, 6.321900849331506946977e-01),
+ };
+ if(x < tools::log_max_value<T>())
+ return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
+ else
+ {
+ T ex = exp(-x / 2);
+ return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
+ }
+ }
+ }
+
+ template <typename T>
+ T bessel_k1_imp(const T& x, const mpl::int_<113>&)
+ {
+ BOOST_MATH_STD_USING
+ if(x <= 1)
+ {
+ // Maximum Deviation Found: 7.120e-35
+ // Expected Error Term : -7.119e-35
+ // Maximum Relative Change in Control Points : 1.207e-03
+ // Max Error found at float128 precision = Poly : 7.143688e-35
+ static const T Y = 8.695471286773681640625000000000000000e-02f;
+ static const T P[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.621379534403483072916666666666595475e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.074117676930975433219826471336547627e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.631337631362776369069668419033041661e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.468935967870048731821071646104412775e-06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.956705020559599861444492614737168261e-08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.347140307321161346703214099534250263e-10),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.569608494081482873946791086435679661e-13)
+ };
+ static const T Q[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.580768910152105375615558920428350204e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.197467671701485365363068445534557369e-04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -6.707466533308630411966030561446666237e-06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.846687802282250112624373388491123527e-08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.248493131151981569517383040323900343e-10),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.319279786372775264555728921709381080e-13)
+ };
+
+ T a = x * x / 4;
+ a = ((tools::evaluate_rational(P, Q, a) + Y) * a * a + a / 2 + 1) * x / 2;
+
+ // Maximum Deviation Found: 4.473e-37
+ // Expected Error Term : 4.473e-37
+ // Maximum Relative Change in Control Points : 8.550e-04
+ // Max Error found at float128 precision = Poly : 8.167701e-35
+ static const T P2[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.079657578292062244053600156878870690e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -8.133183745732467770755578848987414875e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.548968792764174773125420229299431951e-03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -5.886125468718182876076972186152445490e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.506712111733707245745396404449639865e-07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.632502325880313239698965376754406011e-09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.311973065898784812266544485665624227e-12)
+ };
+ static const T Q2[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.311471216733781016657962995723287450e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.571876054797365417068164018709472969e-05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.630181215268238731442496851497901293e-07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.070176111227805048604885986867484807e-09),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.129046580769872602793220056461084761e-12),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.294906469421390890762001971790074432e-15)
+ };
+
+ return tools::evaluate_rational(P2, Q2, T(x * x)) * x + 1 / x + log(x) * a;
+ }
+ else if(x < 4)
+ {
+ // Max error in interpolated form: 5.307e-37
+ // Max Error found at float128 precision = Poly: 7.087862e-35
+ static const T Y = 1.5023040771484375f;
+ static const T P[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.489899398329369710528254347931380044e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -6.819080211203854781858815596508456873e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -7.599915699069767382647695624952723034e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -4.450211910821295507926582231071300718e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.451374687870925175794150513723956533e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -2.405805746895098802803503988539098226e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -5.638808326778389656403861103277220518e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.513958744081268456191778822780865708e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.121301640926540743072258116122834804e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.080094900175649541266613109971296190e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.896531083639613332407534434915552429e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.856602122319645694042555107114028437e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.237121918853145421414003823957537419e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.842072954561323076230238664623893504e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.039705646510167437971862966128055524e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.008418100718254816100425022904039530e-02)
+ };
+ static const T Q[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.927456835239137986889227412815459529e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.598985593265577043711382994516531273e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.449897377085510281395819892689690579e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.025555887684561913263090023158085327e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.774140447181062463181892531100679195e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.962055507843204417243602332246120418e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.908269326976180183216954452196772931e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.655160454422016855911700790722577942e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.383586885019548163464418964577684608e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.679920375586960324298491662159976419e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.478586421028842906987799049804565008e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.565384974896746094224942654383537090e+02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.902617937084010911005732488607114511e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.429293010387921526110949911029094926e-01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.880342607911083143560111853491047663e-04)
+ };
+ return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
+ }
+ else
+ {
+ // Maximum Deviation Found: 4.359e-37
+ // Expected Error Term : -6.565e-40
+ // Maximum Relative Change in Control Points : 1.880e-01
+ // Max Error found at float128 precision = Poly : 2.943572e-35
+ static const T Y = 1.308816909790039062500000000000000000f;
+ static const T P[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, -5.550277247453881129211735759447737350e-02),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -3.485883080219574328217554864956175929e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -8.903760658131484239300875153154881958e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -1.144813672213626237418235110712293337e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, -6.498400501156131446691826557494158173e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.573531831870363502604119835922166116e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.417416550054632009958262596048841154e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.271266450613557412825896604269130661e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.898386013314389952534433455681107783e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 5.353798784656436259250791761023512750e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 9.839619195427352438957774052763490067e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.169246368651532232388152442538005637e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.696368884166831199967845883371116431e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.810226630422736458064005843327500169e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.854996610560406127438950635716757614e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 8.981057433937398731355768088809437625e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.519440069856232098711793483639792952e+04)
+ };
+ static const T Q[] =
+ {
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 7.127348248283623146544565916604103560e+01),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.205092684176906740104488180754982065e+03),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.911249195069050636298346469740075758e+04),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.426103406579046249654548481377792614e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.365861555422488771286500241966208541e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.765377714160383676864913709252529840e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 6.453822726931857253365138260720815246e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.643207885048369990391975749439783892e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.882540678243694621895816336640877878e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.410120808992380266174106812005338148e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.628138016559335882019310900426773027e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.250794693811010646965360198541047961e+08),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 3.378723408195485594610593014072950078e+07),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 4.488253856312453816451380319061865560e+06),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 2.202167197882689873967723350537104582e+05),
+ BOOST_MATH_BIG_CONSTANT(T, 113, 1.673233230356966539460728211412989843e+03)
+ };
+ if(x < tools::log_max_value<T>())
+ return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
+ else
+ {
+ T ex = exp(-x / 2);
+ return ((tools::evaluate_polynomial(P, T(1 / x)) / tools::evaluate_polynomial(Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
+ }
+ }
}
- else // x in (1, \infty)
+
+ template <typename T>
+ T bessel_k1_imp(const T& x, const mpl::int_<0>&)
{
- T y = 1 / x;
- r = evaluate_polynomial(P3, y) / evaluate_polynomial(Q3, y);
- factor = exp(-x) / sqrt(x);
- value = factor * r;
+ if(boost::math::tools::digits<T>() <= 24)
+ return bessel_k1_imp(x, mpl::int_<24>());
+ else if(boost::math::tools::digits<T>() <= 53)
+ return bessel_k1_imp(x, mpl::int_<53>());
+ else if(boost::math::tools::digits<T>() <= 64)
+ return bessel_k1_imp(x, mpl::int_<64>());
+ else if(boost::math::tools::digits<T>() <= 113)
+ return bessel_k1_imp(x, mpl::int_<113>());
+ BOOST_ASSERT(0);
+ return 0;
}
- return value;
-}
+ template <typename T>
+ inline T bessel_k1(const T& x)
+ {
+ typedef mpl::int_<
+ std::numeric_limits<T>::digits == 0 ?
+ 0 :
+ std::numeric_limits<T>::digits <= 24 ?
+ 24 :
+ std::numeric_limits<T>::digits <= 53 ?
+ 53 :
+ std::numeric_limits<T>::digits <= 64 ?
+ 64 :
+ std::numeric_limits<T>::digits <= 113 ?
+ 113 : -1
+ > tag_type;
+
+ bessel_k1_initializer<T, tag_type>::force_instantiate();
+ return bessel_k1_imp(x, tag_type());
+ }
}}} // namespaces
diff --git a/boost/math/special_functions/detail/bessel_kn.hpp b/boost/math/special_functions/detail/bessel_kn.hpp
index e3a5023c63..54c4a1cfa7 100644
--- a/boost/math/special_functions/detail/bessel_kn.hpp
+++ b/boost/math/special_functions/detail/bessel_kn.hpp
@@ -45,16 +45,16 @@ T bessel_kn(int n, T x, const Policy& pol)
}
if (n == 0)
{
- value = bessel_k0(x, pol);
+ value = bessel_k0(x);
}
else if (n == 1)
{
- value = bessel_k1(x, pol);
+ value = bessel_k1(x);
}
else
{
- prev = bessel_k0(x, pol);
- current = bessel_k1(x, pol);
+ prev = bessel_k0(x);
+ current = bessel_k1(x);
int k = 1;
BOOST_ASSERT(k < n);
T scale = 1;
diff --git a/boost/math/special_functions/erf.hpp b/boost/math/special_functions/erf.hpp
index f7f75b0bc7..8d3ee925f4 100644
--- a/boost/math/special_functions/erf.hpp
+++ b/boost/math/special_functions/erf.hpp
@@ -155,12 +155,18 @@ T erf_imp(T z, bool invert, const Policy& pol, const Tag& t)
result = tgamma_small_upper_part(T(0.5f), x, pol);
result /= sqrt(boost::math::constants::pi<T>());
}
+ else if(x > 1 / tools::epsilon<T>())
+ {
+ // http://functions.wolfram.com/06.27.06.0006.02
+ invert = !invert;
+ result = exp(-x) / (constants::root_pi<T>() * z);
+ }
else
{
// Compute Q:
invert = !invert;
result = z * exp(-x);
- result /= sqrt(boost::math::constants::pi<T>());
+ result /= boost::math::constants::root_pi<T>();
result *= upper_gamma_fraction(T(0.5f), x, policies::get_epsilon<T, Policy>());
}
}
diff --git a/boost/math/special_functions/expm1.hpp b/boost/math/special_functions/expm1.hpp
index 7423dc5c81..9cecc89756 100644
--- a/boost/math/special_functions/expm1.hpp
+++ b/boost/math/special_functions/expm1.hpp
@@ -107,6 +107,10 @@ T expm1_imp(T x, const mpl::int_<0>&, const Policy& pol)
BOOST_MATH_STD_USING
T a = fabs(x);
+ if((boost::math::isnan)(a))
+ {
+ return policies::raise_domain_error<T>("boost::math::expm1<%1%>(%1%)", "expm1 requires a finite argument, but got %1%", a, pol);
+ }
if(a > T(0.5f))
{
if(a >= tools::log_max_value<T>())
diff --git a/boost/math/special_functions/gamma.hpp b/boost/math/special_functions/gamma.hpp
index 4161a88395..1903b997cb 100644
--- a/boost/math/special_functions/gamma.hpp
+++ b/boost/math/special_functions/gamma.hpp
@@ -391,8 +391,8 @@ T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&)
// Check if the argument of tgamma is identically zero.
const bool is_at_zero = (z == 0);
- if(is_at_zero)
- return policies::raise_domain_error<T>(function, "Evaluation of tgamma at zero %1%.", z, pol);
+ if((is_at_zero) || ((boost::math::isinf)(z) && (z < 0)))
+ return policies::raise_domain_error<T>(function, "Evaluation of tgamma at %1%.", z, pol);
const bool b_neg = (z < 0);
@@ -538,6 +538,10 @@ T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&, int* sig
if(is_at_zero)
return policies::raise_domain_error<T>(function, "Evaluation of lgamma at zero %1%.", z, pol);
+ if((boost::math::isnan)(z))
+ return policies::raise_domain_error<T>(function, "Evaluation of lgamma at %1%.", z, pol);
+ if((boost::math::isinf)(z))
+ return policies::raise_overflow_error<T>(function, 0, pol);
const bool b_neg = (z < 0);
diff --git a/boost/math/special_functions/log1p.hpp b/boost/math/special_functions/log1p.hpp
index 50bdaeb385..7fa1eb8de9 100644
--- a/boost/math/special_functions/log1p.hpp
+++ b/boost/math/special_functions/log1p.hpp
@@ -80,7 +80,7 @@ T log1p_imp(T const & x, const Policy& pol, const mpl::int_<0>&)
static const char* function = "boost::math::log1p<%1%>(%1%)";
- if(x < -1)
+ if((x < -1) || (boost::math::isnan)(x))
return policies::raise_domain_error<T>(
function, "log1p(x) requires x > -1, but got x = %1%.", x, pol);
if(x == -1)
diff --git a/boost/math/special_functions/math_fwd.hpp b/boost/math/special_functions/math_fwd.hpp
index ca8e58144e..efb8f067ac 100644
--- a/boost/math/special_functions/math_fwd.hpp
+++ b/boost/math/special_functions/math_fwd.hpp
@@ -626,6 +626,17 @@ namespace boost
bessel_maybe_int_tag
>::type
>::type optimisation_tag;
+ typedef typename mpl::if_<
+ mpl::or_<
+ mpl::less_equal<precision_type, mpl::int_<0> >,
+ mpl::greater<precision_type, mpl::int_<113> > >,
+ bessel_no_int_tag,
+ typename mpl::if_<
+ is_integral<T1>,
+ bessel_int_tag,
+ bessel_maybe_int_tag
+ >::type
+ >::type optimisation_tag128;
};
} // detail
diff --git a/boost/math/special_functions/next.hpp b/boost/math/special_functions/next.hpp
index 9602bc7697..3921b70ce0 100644
--- a/boost/math/special_functions/next.hpp
+++ b/boost/math/special_functions/next.hpp
@@ -144,9 +144,9 @@ T float_next_imp(const T& val, const Policy& pol)
if(diff == 0)
diff = detail::get_smallest_value<T>();
return val + diff;
-}
+} // float_next_imp
-}
+} // namespace detail
template <class T, class Policy>
inline typename tools::promote_args<T>::type float_next(const T& val, const Policy& pol)
@@ -227,9 +227,9 @@ T float_prior_imp(const T& val, const Policy& pol)
if(diff == 0)
diff = detail::get_smallest_value<T>();
return val - diff;
-}
+} // float_prior_imp
-}
+} // namespace detail
template <class T, class Policy>
inline typename tools::promote_args<T>::type float_prior(const T& val, const Policy& pol)
@@ -304,7 +304,7 @@ T float_distance_imp(const T& a, const T& b, const Policy& pol)
if(a > b)
return -float_distance(b, a, pol);
if(a == b)
- return 0;
+ 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)
@@ -330,7 +330,7 @@ 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 = 0;
+ T result = T(0);
expon = tools::digits<T>() - expon;
//
// If b is greater than upper, then we *must* split the calculation
@@ -379,9 +379,9 @@ T float_distance_imp(const T& a, const T& b, const Policy& pol)
//
BOOST_ASSERT(result == floor(result));
return result;
-}
+} // float_distance_imp
-}
+} // namespace detail
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)
@@ -477,9 +477,9 @@ T float_advance_imp(T val, int distance, const Policy& pol)
if(diff == 0)
diff = distance * detail::get_smallest_value<T>();
return val += diff;
-}
+} // float_advance_imp
-}
+} // namespace detail
template <class T, class Policy>
inline typename tools::promote_args<T>::type float_advance(T val, int distance, const Policy& pol)
@@ -494,7 +494,7 @@ inline typename tools::promote_args<T>::type float_advance(const T& val, int dis
return boost::math::float_advance(val, distance, policies::policy<>());
}
-}} // namespaces
+}} // boost math namespaces
#endif // BOOST_MATH_SPECIAL_NEXT_HPP
diff --git a/boost/math/tools/config.hpp b/boost/math/tools/config.hpp
index 32375e6a6e..8131facb98 100644
--- a/boost/math/tools/config.hpp
+++ b/boost/math/tools/config.hpp
@@ -31,7 +31,7 @@
#if (defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__NetBSD__) \
|| (defined(__hppa) && !defined(__OpenBSD__)) || (defined(__NO_LONG_DOUBLE_MATH) && (DBL_MANT_DIG != LDBL_MANT_DIG))) \
&& !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
-# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
+//# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
#endif
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
//
diff --git a/boost/move/default_delete.hpp b/boost/move/default_delete.hpp
index 1c26ed924b..31ae67aa07 100644
--- a/boost/move/default_delete.hpp
+++ b/boost/move/default_delete.hpp
@@ -96,6 +96,22 @@ typedef int bool_conversion::* explicit_bool_arg;
typedef int (bool_conversion::*nullptr_type)();
#endif
+template<bool B>
+struct is_array_del
+{};
+
+template<class T>
+void call_delete(T *p, is_array_del<true>)
+{
+ delete [] p;
+}
+
+template<class T>
+void call_delete(T *p, is_array_del<false>)
+{
+ delete p;
+}
+
} //namespace move_upd {
// @endcond
@@ -184,7 +200,7 @@ struct default_delete
//and T has no virtual destructor, then you have a problem
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
element_type * const p = static_cast<element_type*>(ptr);
- bmupmu::is_array<T>::value ? delete [] p : delete p;
+ move_upd::call_delete(p, move_upd::is_array_del<bmupmu::is_array<T>::value>());
}
//! <b>Effects</b>: Same as <tt>(*this)(static_cast<element_type*>(nullptr))</tt>.
diff --git a/boost/move/detail/unique_ptr_meta_utils.hpp b/boost/move/detail/unique_ptr_meta_utils.hpp
index 33720683de..ac270a8fc0 100644
--- a/boost/move/detail/unique_ptr_meta_utils.hpp
+++ b/boost/move/detail/unique_ptr_meta_utils.hpp
@@ -397,7 +397,7 @@ struct pointer_type_imp
template <class T, class D>
struct pointer_type_imp<T, D, false>
{
- typedef typename remove_extent<T>::type* type;
+ typedef T* type;
};
template <class T, class D>
diff --git a/boost/multi_index/detail/archive_constructed.hpp b/boost/multi_index/detail/archive_constructed.hpp
index c3891bb32a..0a7a26e0d4 100644
--- a/boost/multi_index/detail/archive_constructed.hpp
+++ b/boost/multi_index/detail/archive_constructed.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2003-2015 Joaquin M Lopez Munoz.
+/* Copyright 2003-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)
@@ -64,8 +64,12 @@ struct archive_constructed:private noncopyable
(&get())->~T();
}
+#include <boost/multi_index/detail/ignore_wstrict_aliasing.hpp>
+
T& get(){return *reinterpret_cast<T*>(&space);}
+#include <boost/multi_index/detail/restore_wstrict_aliasing.hpp>
+
private:
typename aligned_storage<sizeof(T),alignment_of<T>::value>::type space;
};
diff --git a/boost/multi_index/detail/ignore_wstrict_aliasing.hpp b/boost/multi_index/detail/ignore_wstrict_aliasing.hpp
new file mode 100644
index 0000000000..ae398456d1
--- /dev/null
+++ b/boost/multi_index/detail/ignore_wstrict_aliasing.hpp
@@ -0,0 +1,18 @@
+/* Copyright 2003-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/multi_index for library home page.
+ */
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_GCC)&&(BOOST_GCC>=4*10000+6*100)
+#if !defined(BOOST_MULTI_INDEX_DETAIL_RESTORE_WSTRICT_ALIASING)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#else
+#pragma GCC diagnostic pop
+#endif
+#endif
diff --git a/boost/multi_index/detail/index_node_base.hpp b/boost/multi_index/detail/index_node_base.hpp
index e6fabe62bb..1a1f0cae4b 100644
--- a/boost/multi_index/detail/index_node_base.hpp
+++ b/boost/multi_index/detail/index_node_base.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2003-2015 Joaquin M Lopez Munoz.
+/* Copyright 2003-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)
@@ -49,6 +49,8 @@ struct index_node_base:private pod_value_holder<Value>
typedef Value value_type;
typedef Allocator allocator_type;
+#include <boost/multi_index/detail/ignore_wstrict_aliasing.hpp>
+
value_type& value()
{
return *reinterpret_cast<value_type*>(&this->space);
@@ -59,6 +61,8 @@ struct index_node_base:private pod_value_holder<Value>
return *reinterpret_cast<const value_type*>(&this->space);
}
+#include <boost/multi_index/detail/restore_wstrict_aliasing.hpp>
+
static index_node_base* from_value(const value_type* p)
{
return static_cast<index_node_base *>(
diff --git a/boost/multi_index/detail/promotes_arg.hpp b/boost/multi_index/detail/promotes_arg.hpp
index 75cf4368cf..7a11b6e9fb 100644
--- a/boost/multi_index/detail/promotes_arg.hpp
+++ b/boost/multi_index/detail/promotes_arg.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2003-2014 Joaquin M Lopez Munoz.
+/* Copyright 2003-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)
@@ -14,15 +14,14 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
-#include <boost/mpl/bool.hpp>
-#include <boost/type_traits/intrinsics.hpp>
+#include <boost/detail/workaround.hpp>
/* Metafunctions to check if f(arg1,arg2) promotes either arg1 to the type of
* arg2 or viceversa. By default, (i.e. if it cannot be determined), no
* promotion is assumed.
*/
-#if !defined(BOOST_IS_CONVERTIBLE)
+#if BOOST_WORKAROUND(BOOST_MSVC,<1400)
namespace boost{
@@ -45,6 +44,7 @@ struct promotes_2nd_arg:mpl::false_{};
#else
#include <boost/mpl/and.hpp>
+#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/multi_index/detail/is_transparent.hpp>
#include <boost/type_traits/is_convertible.hpp>
@@ -79,5 +79,5 @@ struct promotes_2nd_arg:
} /* namespace boost */
-#endif /* defined(BOOST_IS_CONVERTIBLE) */
+#endif
#endif
diff --git a/boost/multi_index/detail/restore_wstrict_aliasing.hpp b/boost/multi_index/detail/restore_wstrict_aliasing.hpp
new file mode 100644
index 0000000000..ee2c799d5a
--- /dev/null
+++ b/boost/multi_index/detail/restore_wstrict_aliasing.hpp
@@ -0,0 +1,11 @@
+/* Copyright 2003-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/multi_index for library home page.
+ */
+
+#define BOOST_MULTI_INDEX_DETAIL_RESTORE_WSTRICT_ALIASING
+#include <boost/multi_index/detail/ignore_wstrict_aliasing.hpp>
+#undef BOOST_MULTI_INDEX_DETAIL_RESTORE_WSTRICT_ALIASING
diff --git a/boost/multi_index/detail/rnk_index_ops.hpp b/boost/multi_index/detail/rnk_index_ops.hpp
index 275642236b..fb233cf497 100644
--- a/boost/multi_index/detail/rnk_index_ops.hpp
+++ b/boost/multi_index/detail/rnk_index_ops.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2003-2015 Joaquin M Lopez Munoz.
+/* Copyright 2003-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)
@@ -109,7 +109,7 @@ inline std::size_t ranked_index_find_rank(
{
if(!top)return 0;
- std::size_t s=top->size,
+ std::size_t s=top->impl()->size,
s0=s;
Node* y0=y;
@@ -162,7 +162,7 @@ inline std::size_t ranked_index_lower_bound_rank(
{
if(!top)return 0;
- std::size_t s=top->size;
+ std::size_t s=top->impl()->size;
do{
if(!comp(key(top->value()),x)){
@@ -213,7 +213,7 @@ inline std::size_t ranked_index_upper_bound_rank(
{
if(!top)return 0;
- std::size_t s=top->size;
+ std::size_t s=top->impl()->size;
do{
if(comp(x,key(top->value()))){
@@ -266,7 +266,7 @@ inline std::pair<std::size_t,std::size_t> ranked_index_equal_range_rank(
{
if(!top)return std::pair<std::size_t,std::size_t>(0,0);
- std::size_t s=top->size;
+ std::size_t s=top->impl()->size;
do{
if(comp(key(top->value()),x)){
@@ -279,7 +279,7 @@ inline std::pair<std::size_t,std::size_t> ranked_index_equal_range_rank(
}
else{
return std::pair<std::size_t,std::size_t>(
- s-top->size+
+ s-top->impl()->size+
ranked_index_lower_bound_rank(
Node::from_impl(top->left()),top,key,x,comp,mpl::false_()),
s-ranked_node_size(top->right())+
diff --git a/boost/multi_index/detail/seq_index_ops.hpp b/boost/multi_index/detail/seq_index_ops.hpp
index a3c2bc1f04..142bdd9dd9 100644
--- a/boost/multi_index/detail/seq_index_ops.hpp
+++ b/boost/multi_index/detail/seq_index_ops.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2003-2015 Joaquin M Lopez Munoz.
+/* Copyright 2003-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)
@@ -110,6 +110,8 @@ BOOST_STATIC_CONSTANT(
sequenced_index_sort_max_fill=
(std::size_t)std::numeric_limits<std::size_t>::digits+1);
+#include <boost/multi_index/detail/ignore_wstrict_aliasing.hpp>
+
template<typename Node,typename Compare>
void sequenced_index_sort(Node* header,Compare comp)
{
@@ -190,6 +192,8 @@ void sequenced_index_sort(Node* header,Compare comp)
BOOST_CATCH_END
}
+#include <boost/multi_index/detail/restore_wstrict_aliasing.hpp>
+
} /* namespace multi_index::detail */
} /* namespace multi_index */
diff --git a/boost/multi_index/ranked_index.hpp b/boost/multi_index/ranked_index.hpp
index 4fd4d32c75..4b24c4f593 100644
--- a/boost/multi_index/ranked_index.hpp
+++ b/boost/multi_index/ranked_index.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2003-2015 Joaquin M Lopez Munoz.
+/* Copyright 2003-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)
@@ -165,7 +165,7 @@ private:
if(!z)return std::pair<std::size_t,std::size_t>(0,0);
- std::size_t s=z->size;
+ std::size_t s=z->impl()->size;
do{
if(!lower(this->key(z->value()))){
@@ -178,7 +178,7 @@ private:
}
else{
return std::pair<std::size_t,std::size_t>(
- s-z->size+
+ s-z->impl()->size+
lower_range_rank(node_type::from_impl(z->left()),z,lower),
s-ranked_node_size(z->right())+
upper_range_rank(node_type::from_impl(z->right()),y,upper));
@@ -219,7 +219,7 @@ private:
{
if(!top)return 0;
- std::size_t s=top->size;
+ std::size_t s=top->impl()->size;
do{
if(lower(this->key(top->value()))){
@@ -239,7 +239,7 @@ private:
{
if(!top)return 0;
- std::size_t s=top->size;
+ std::size_t s=top->impl()->size;
do{
if(!upper(this->key(top->value()))){
diff --git a/boost/multiprecision/cpp_bin_float.hpp b/boost/multiprecision/cpp_bin_float.hpp
index 38f5387528..f3e593a142 100644
--- a/boost/multiprecision/cpp_bin_float.hpp
+++ b/boost/multiprecision/cpp_bin_float.hpp
@@ -21,6 +21,10 @@
#include <boost/math/special_functions/expm1.hpp>
#include <boost/math/special_functions/gamma.hpp>
+#ifdef BOOST_HAS_FLOAT128
+#include <quadmath.h>
+#endif
+
namespace boost{ namespace multiprecision{ namespace backends{
enum digit_base_type
@@ -163,6 +167,64 @@ public:
return assign_float(f);
}
+#ifdef BOOST_HAS_FLOAT128
+ cpp_bin_float& operator=(__float128 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);
+ m_sign = (signbitq(f) > 0);
+ m_exponent = exponent_zero;
+ return *this;
+ }
+ else if(isnanq(f))
+ {
+ m_data = limb_type(0);
+ m_sign = false;
+ m_exponent = exponent_nan;
+ return *this;
+ }
+ else if(isinfq(f))
+ {
+ m_data = limb_type(0);
+ m_sign = (f < 0);
+ m_exponent = exponent_infinity;
+ return *this;
+ }
+ if(f < 0)
+ {
+ *this = -f;
+ this->negate();
+ return *this;
+ }
+
+ typedef typename mpl::front<unsigned_types>::type ui_type;
+ m_data = static_cast<ui_type>(0u);
+ m_sign = false;
+ m_exponent = 0;
+
+ static const int bits = sizeof(int) * CHAR_BIT - 1;
+ int e;
+ f = frexpq(f, &e);
+ while(f)
+ {
+ f = ldexpq(f, bits);
+ e -= bits;
+ int ipart = (int)truncq(f);
+ f -= ipart;
+ m_exponent += bits;
+ cpp_bin_float t;
+ t = static_cast<bf_int_type>(ipart);
+ eval_add(*this, t);
+ }
+ m_exponent += static_cast<Exponent>(e);
+ return *this;
+ }
+#endif
+
template <class Float>
typename boost::enable_if_c<is_floating_point<Float>::value, cpp_bin_float&>::type assign_float(Float f)
{
@@ -414,10 +476,10 @@ public:
#endif
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class Int>
-inline void copy_and_round(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, Int &arg)
+inline void copy_and_round(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, Int &arg, int bits_to_keep = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
{
// Precondition: exponent of res must have been set before this function is called
- // as we may need to adjust it based on how many cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in arg are set.
+ // as we may need to adjust it based on how many bits_to_keep in arg are set.
using default_ops::eval_msb;
using default_ops::eval_lsb;
using default_ops::eval_left_shift;
@@ -435,45 +497,70 @@ inline void copy_and_round(cpp_bin_float<Digits, DigitBase, Allocator, Exponent,
return;
}
int msb = eval_msb(arg);
- if(static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) > msb + 1)
+ if(static_cast<int>(bits_to_keep) > msb + 1)
{
- // Must have had cancellation in subtraction, shift left and copy:
+ // Must have had cancellation in subtraction,
+ // or be converting from a narrower type, so shift left:
res.bits() = arg;
- eval_left_shift(res.bits(), cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - msb - 1);
- res.exponent() -= static_cast<Exponent>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - msb - 1);
+ eval_left_shift(res.bits(), bits_to_keep - msb - 1);
+ res.exponent() -= static_cast<Exponent>(bits_to_keep - msb - 1);
}
- else if(static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) < msb + 1)
+ else if(static_cast<int>(bits_to_keep) < msb + 1)
{
- // We have more cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count than we need, so round as required,
+ // We have more bits_to_keep than we need, so round as required,
// first get the rounding bit:
- bool roundup = eval_bit_test(arg, msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count);
+ bool roundup = eval_bit_test(arg, msb - bits_to_keep);
// Then check for a tie:
- if(roundup && (msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count == eval_lsb(arg)))
+ if(roundup && (msb - bits_to_keep == (int)eval_lsb(arg)))
{
// Ties round towards even:
- if(!eval_bit_test(arg, msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1))
+ if(!eval_bit_test(arg, msb - bits_to_keep + 1))
roundup = false;
}
- // Shift off the cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count we don't need:
- eval_right_shift(arg, msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1);
- res.exponent() += static_cast<Exponent>(msb - (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1);
+ // Shift off the bits_to_keep we don't need:
+ eval_right_shift(arg, msb - bits_to_keep + 1);
+ res.exponent() += static_cast<Exponent>(msb - bits_to_keep + 1);
if(roundup)
{
eval_increment(arg);
- if(eval_bit_test(arg, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
+ if(bits_to_keep)
+ {
+ if(eval_bit_test(arg, bits_to_keep))
+ {
+ // This happens very very rairly, all the bits left after
+ // truncation must be 1's and we're rounding up an order of magnitude:
+ eval_right_shift(arg, 1u);
+ ++res.exponent();
+ }
+ }
+ else
{
- // This happens very very rairly:
- eval_right_shift(arg, 1u);
- ++res.exponent();
+ // We get here when bits_to_keep is zero but we're rounding up,
+ // as a result we end up with a single digit that is a 1:
+ ++bits_to_keep;
}
}
+ if(bits_to_keep != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
+ {
+ // Normalize result when we're rounding to fewer bits than we can hold, only happens in conversions
+ // to narrower types:
+ eval_left_shift(arg, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - bits_to_keep);
+ res.exponent() -= static_cast<Exponent>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - bits_to_keep);
+ }
res.bits() = arg;
}
else
{
res.bits() = arg;
}
- BOOST_ASSERT((eval_msb(res.bits()) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
+ if(!bits_to_keep && !res.bits().limbs()[0])
+ {
+ // We're keeping zero bits and did not round up, so result is zero:
+ res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
+ return;
+ }
+ // Result must be normalized:
+ BOOST_ASSERT(((int)eval_msb(res.bits()) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
if(res.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
{
@@ -571,6 +658,7 @@ inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponen
{
using default_ops::eval_subtract;
using default_ops::eval_bit_test;
+ using default_ops::eval_decrement;
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
@@ -626,19 +714,41 @@ inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponen
res.exponent() = a.exponent() - e_diff;
eval_subtract(dt, b.bits());
}
+ else if(a.exponent() == (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + b.exponent() + 1)
+ {
+ if(eval_lsb(b.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
+ {
+ eval_left_shift(dt, 1);
+ eval_decrement(dt);
+ res.exponent() = a.exponent() - 1;
+ }
+ else
+ res.exponent() = a.exponent();
+ }
else
res.exponent() = a.exponent();
}
else
{
dt = b.bits();
- if(b.exponent() <= a.exponent() + (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
+ if(b.exponent() <= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + a.exponent())
{
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
eval_left_shift(dt, -e_diff);
res.exponent() = b.exponent() + e_diff;
eval_subtract(dt, a.bits());
}
+ else if(b.exponent() == (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + a.exponent() + 1)
+ {
+ if(eval_lsb(a.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
+ {
+ eval_left_shift(dt, 1);
+ eval_decrement(dt);
+ res.exponent() = b.exponent() - 1;
+ }
+ else
+ res.exponent() = b.exponent();
+ }
else
res.exponent() = b.exponent();
s = !s;
@@ -1232,50 +1342,77 @@ inline void eval_convert_to(boost::ulong_long_type *res, const cpp_bin_float<Dig
template <class Float, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
inline typename boost::enable_if_c<boost::is_float<Float>::value>::type eval_convert_to(Float *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &original_arg)
{
- //
- // Perform rounding first, then afterwards extract the digits:
- //
typedef cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE> conv_type;
typedef typename common_type<typename conv_type::exponent_type, int>::type common_exp_type;
- conv_type arg(original_arg);
- switch(arg.exponent())
+ //
+ // Special cases first:
+ //
+ switch(original_arg.exponent())
{
- case conv_type::exponent_zero:
+ case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
*res = 0;
- if(arg.sign())
+ if(original_arg.sign())
*res = -*res;
return;
- case conv_type::exponent_nan:
+ case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
*res = std::numeric_limits<Float>::quiet_NaN();
return;
- case conv_type::exponent_infinity:
+ case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
*res = (std::numeric_limits<Float>::infinity)();
- if(arg.sign())
+ if(original_arg.sign())
*res = -*res;
return;
}
- common_exp_type e = arg.exponent();
- static const common_exp_type min_exp_limit = std::numeric_limits<Float>::min_exponent
- - (common_exp_type)cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE>::bit_count - std::numeric_limits<Float>::digits - 2;
- e -= cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE>::bit_count - 1;
- if(e < min_exp_limit)
+ //
+ // Check for super large exponent that must be converted to infinity:
+ //
+ if(original_arg.exponent() > std::numeric_limits<Float>::max_exponent)
{
- *res = 0;
+ *res = std::numeric_limits<Float>::has_infinity ? std::numeric_limits<Float>::infinity() : (std::numeric_limits<Float>::max)();
+ if(original_arg.sign())
+ *res = -*res;
return;
}
- if(e > std::numeric_limits<Float>::max_exponent)
+ //
+ // Figure out how many digits we will have in our result,
+ // allowing for a possibly denormalized result:
+ //
+ common_exp_type digits_to_round_to = std::numeric_limits<Float>::digits;
+ if(original_arg.exponent() < std::numeric_limits<Float>::min_exponent - 1)
{
- *res = std::numeric_limits<Float>::has_infinity ? std::numeric_limits<Float>::infinity() : (std::numeric_limits<Float>::max)();
- return;
+ common_exp_type diff = original_arg.exponent();
+ diff -= std::numeric_limits<Float>::min_exponent - 1;
+ digits_to_round_to += diff;
}
-
- *res = std::ldexp(static_cast<Float>(*arg.bits().limbs()), static_cast<int>(e));
- for(unsigned i = 1; i < arg.bits().size(); ++i)
+ if(digits_to_round_to < 0)
{
+ // Result must be zero:
+ *res = 0;
+ if(original_arg.sign())
+ *res = -*res;
+ return;
+ }
+ //
+ // Perform rounding first, then afterwards extract the digits:
+ //
+ cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, Allocator, Exponent, MinE, MaxE> arg;
+ typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type bits(original_arg.bits());
+ arg.exponent() = original_arg.exponent();
+ copy_and_round(arg, bits, (int)digits_to_round_to);
+ common_exp_type e = arg.exponent();
+ e -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1;
+ static const unsigned limbs_needed = std::numeric_limits<Float>::digits / (sizeof(*arg.bits().limbs()) * CHAR_BIT)
+ + (std::numeric_limits<Float>::digits % (sizeof(*arg.bits().limbs()) * CHAR_BIT) ? 1 : 0);
+ unsigned first_limb_needed = arg.bits().size() - limbs_needed;
+ *res = 0;
+ e += first_limb_needed * sizeof(*arg.bits().limbs()) * CHAR_BIT;
+ while(first_limb_needed < arg.bits().size())
+ {
+ *res += std::ldexp(static_cast<Float>(arg.bits().limbs()[first_limb_needed]), static_cast<int>(e));
+ ++first_limb_needed;
e += sizeof(*arg.bits().limbs()) * CHAR_BIT;
- *res += std::ldexp(static_cast<Float>(arg.bits().limbs()[i]), static_cast<int>(e));
}
- if(arg.sign())
+ if(original_arg.sign())
*res = -*res;
}
@@ -1401,13 +1538,18 @@ inline void eval_sqrt(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE
using default_ops::eval_increment;
switch(arg.exponent())
{
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
+ errno = EDOM;
+ // fallthrough...
+ case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
res = arg;
return;
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
if(arg.sign())
+ {
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
+ errno = EDOM;
+ }
else
res = arg;
return;
@@ -1415,6 +1557,7 @@ inline void eval_sqrt(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE
if(arg.sign())
{
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
+ errno = EDOM;
return;
}
@@ -1443,8 +1586,10 @@ inline void eval_floor(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, Min
using default_ops::eval_increment;
switch(arg.exponent())
{
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
+ errno = EDOM;
+ // fallthrough...
+ case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
res = arg;
return;
@@ -1484,9 +1629,11 @@ inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE
using default_ops::eval_increment;
switch(arg.exponent())
{
+ case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
+ errno = EDOM;
+ // fallthrough...
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
res = arg;
return;
}
@@ -1521,6 +1668,12 @@ inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE
}
template<unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2>
+int eval_signbit(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val)
+{
+ return val.sign();
+}
+
+template<unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2>
inline std::size_t hash_value(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val)
{
std::size_t result = hash_value(val.bits());
@@ -1545,12 +1698,6 @@ struct is_explicitly_convertible<FloatT, backends::cpp_bin_float<D2, B2, A2, E2,
#endif
template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
-inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& arg)
-{
- return arg.backend().sign();
-}
-
-template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
inline boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>
copysign BOOST_PREVENT_MACRO_SUBSTITUTION(
const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& a,
diff --git a/boost/multiprecision/cpp_bin_float/transcendental.hpp b/boost/multiprecision/cpp_bin_float/transcendental.hpp
index 9037dd3982..066bc458e4 100644
--- a/boost/multiprecision/cpp_bin_float/transcendental.hpp
+++ b/boost/multiprecision/cpp_bin_float/transcendental.hpp
@@ -70,6 +70,7 @@ void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>
if(type == (int)FP_NAN)
{
res = arg;
+ errno = EDOM;
return;
}
else if(type == (int)FP_INFINITE)
diff --git a/boost/multiprecision/cpp_dec_float.hpp b/boost/multiprecision/cpp_dec_float.hpp
index 9e0c2900ae..f9e6a22189 100644
--- a/boost/multiprecision/cpp_dec_float.hpp
+++ b/boost/multiprecision/cpp_dec_float.hpp
@@ -1254,9 +1254,15 @@ cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, Expone
{
// Compute the square root of *this.
+ if((isinf)() && !isneg())
+ {
+ return *this;
+ }
+
if(isneg() || (!(isfinite)()))
{
*this = nan();
+ errno = EDOM;
return *this;
}
@@ -2312,6 +2318,11 @@ void cpp_dec_float<Digits10, ExponentType, Allocator>::from_unsigned_long_long(c
fpclass = cpp_dec_float_finite;
prec_elem = cpp_dec_float_elem_number;
+ if(u == 0)
+ {
+ return;
+ }
+
std::size_t i =static_cast<std::size_t>(0u);
boost::ulong_long_type uu = u;
@@ -2822,6 +2833,8 @@ inline void eval_floor(cpp_dec_float<Digits10, ExponentType, Allocator>& result,
result = x;
if(!(x.isfinite)() || x.isint())
{
+ if((x.isnan)())
+ errno = EDOM;
return;
}
@@ -2836,6 +2849,8 @@ inline void eval_ceil(cpp_dec_float<Digits10, ExponentType, Allocator>& result,
result = x;
if(!(x.isfinite)() || x.isint())
{
+ if((x.isnan)())
+ errno = EDOM;
return;
}
@@ -2847,14 +2862,11 @@ inline void eval_ceil(cpp_dec_float<Digits10, ExponentType, Allocator>& result,
template <unsigned Digits10, class ExponentType, class Allocator>
inline void eval_trunc(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x)
{
- if(!(x.isfinite)())
- {
- result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number<cpp_dec_float<Digits10, ExponentType, Allocator> >(x), number<cpp_dec_float<Digits10, ExponentType, Allocator> >(x), boost::math::policies::policy<>()).backend();
- return;
- }
- else if(x.isint())
+ if(x.isint() || !(x.isfinite)())
{
result = x;
+ if((x.isnan)())
+ errno = EDOM;
return;
}
result = x.extract_integer_part();
@@ -2863,6 +2875,16 @@ inline void eval_trunc(cpp_dec_float<Digits10, ExponentType, Allocator>& result,
template <unsigned Digits10, class ExponentType, class Allocator>
inline ExponentType eval_ilogb(const cpp_dec_float<Digits10, ExponentType, Allocator>& val)
{
+ if(val.iszero())
+ return (std::numeric_limits<ExponentType>::min)();
+ if((val.isinf)())
+ return INT_MAX;
+ if((val.isnan)())
+#ifdef FP_ILOGBNAN
+ return FP_ILOGBNAN;
+#else
+ return INT_MAX;
+#endif
// Set result, to the exponent of val:
return val.order();
}
@@ -2897,15 +2919,16 @@ template <unsigned Digits10, class ExponentType, class Allocator>
inline void eval_frexp(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x, ExponentType* e)
{
result = x;
- if(result.isneg())
- result.negate();
- if(result.iszero())
+ if(result.iszero() || (result.isinf)() || (result.isnan)())
{
*e = 0;
return;
}
+ if(result.isneg())
+ result.negate();
+
ExponentType t = result.order();
BOOST_MP_USING_ABS
if(abs(t) < ((std::numeric_limits<ExponentType>::max)() / 1000))
diff --git a/boost/multiprecision/cpp_int/add.hpp b/boost/multiprecision/cpp_int/add.hpp
index 22b8c186dc..2fca9b9597 100644
--- a/boost/multiprecision/cpp_int/add.hpp
+++ b/boost/multiprecision/cpp_int/add.hpp
@@ -84,7 +84,7 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BO
{
// We overflowed, need to add one more limb:
result.resize(x + 1, x + 1);
- if(CppInt1::variable || (result.size() > x))
+ if(result.size() > x)
result.limbs()[x] = static_cast<limb_type>(carry);
}
result.normalize();
@@ -126,7 +126,7 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o)
// We overflowed, need to add one more limb:
unsigned x = result.size();
result.resize(x + 1, x + 1);
- if(CppInt1::variable || (result.size() > x))
+ if(result.size() > x)
result.limbs()[x] = static_cast<limb_type>(carry);
}
result.normalize();
diff --git a/boost/multiprecision/cpp_int/bitwise.hpp b/boost/multiprecision/cpp_int/bitwise.hpp
index 748d088056..168544c9bb 100644
--- a/boost/multiprecision/cpp_int/bitwise.hpp
+++ b/boost/multiprecision/cpp_int/bitwise.hpp
@@ -326,7 +326,7 @@ inline void left_shift_byte(Int& result, double_limb_type s)
if(rs != ors)
pr[rs - 1] = 0u;
std::size_t bytes = static_cast<std::size_t>(s / CHAR_BIT);
- std::size_t len = std::min(ors * sizeof(limb_type), rs * sizeof(limb_type) - bytes);
+ std::size_t len = (std::min)(ors * sizeof(limb_type), rs * sizeof(limb_type) - bytes);
if(bytes >= rs * sizeof(limb_type))
result = static_cast<limb_type>(0u);
else
@@ -411,14 +411,14 @@ inline void left_shift_generic(Int& result, double_limb_type s)
++i;
}
}
- for(; ors > 1 + i; ++i)
+ for(; rs - i >= 2 + offset; ++i)
{
- pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
- pr[rs - 1 - i] |= pr[ors - 2 - i] >> (Int::limb_bits - shift);
+ pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift;
+ pr[rs - 1 - i] |= pr[rs - 2 - i - offset] >> (Int::limb_bits - shift);
}
- if(ors >= 1 + i)
+ if(rs - i >= 1 + offset)
{
- pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
+ pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift;
++i;
}
for(; i < rs; ++i)
diff --git a/boost/multiprecision/cpp_int/divide.hpp b/boost/multiprecision/cpp_int/divide.hpp
index 2f83d1ba71..81583ec384 100644
--- a/boost/multiprecision/cpp_int/divide.hpp
+++ b/boost/multiprecision/cpp_int/divide.hpp
@@ -220,7 +220,7 @@ void divide_unsigned_helper(
//
double_limb_type carry = 0;
t.resize(y.size() + shift + 1, y.size() + shift);
- bool truncated_t = !CppInt1::variable && (t.size() != y.size() + shift + 1);
+ bool truncated_t = (t.size() != y.size() + shift + 1);
typename CppInt1::limb_pointer pt = t.limbs();
for(unsigned i = 0; i < shift; ++i)
pt[i] = 0;
diff --git a/boost/multiprecision/cpp_int/import_export.hpp b/boost/multiprecision/cpp_int/import_export.hpp
index 0fe3249ddc..7bd843fb32 100644
--- a/boost/multiprecision/cpp_int/import_export.hpp
+++ b/boost/multiprecision/cpp_int/import_export.hpp
@@ -134,7 +134,7 @@ namespace boost {
cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& result = val.backend();
result.resize(static_cast<unsigned>(limb_len), static_cast<unsigned>(limb_len)); // checked types may throw here if they're not large enough to hold the data!
result.limbs()[result.size() - 1] = 0u;
- std::memcpy(result.limbs(), i, std::min(byte_len, result.size() * sizeof(limb_type)));
+ std::memcpy(result.limbs(), i, (std::min)(byte_len, result.size() * sizeof(limb_type)));
result.normalize(); // In case data has leading zeros.
return val;
}
@@ -150,7 +150,7 @@ namespace boost {
++limb_len;
result.limbs()[0] = 0u;
result.resize(static_cast<unsigned>(limb_len), static_cast<unsigned>(limb_len)); // checked types may throw here if they're not large enough to hold the data!
- std::memcpy(result.limbs(), i, std::min(byte_len, result.size() * sizeof(result.limbs()[0])));
+ std::memcpy(result.limbs(), i, (std::min)(byte_len, result.size() * sizeof(result.limbs()[0])));
result.normalize(); // In case data has leading zeros.
return val;
}
@@ -199,8 +199,8 @@ namespace boost {
template <class Backend>
inline boost::uintmax_t extract_bits(const Backend& val, unsigned location, unsigned count, const mpl::true_&)
{
- boost::uintmax_t result = *val.limbs();
- boost::uintmax_t mask = count == std::numeric_limits<boost::uintmax_t>::digits ? ~static_cast<boost::uintmax_t>(0) : (static_cast<boost::uintmax_t>(1u) << count) - 1;
+ typename Backend::local_limb_type result = *val.limbs();
+ typename Backend::local_limb_type mask = count >= std::numeric_limits<typename Backend::local_limb_type>::digits ? ~static_cast<typename Backend::local_limb_type>(0) : (static_cast<typename Backend::local_limb_type>(1u) << count) - 1;
return (result >> location) & mask;
}
diff --git a/boost/multiprecision/cpp_int/limits.hpp b/boost/multiprecision/cpp_int/limits.hpp
index 518bb9f4e0..b19e1ebbe6 100644
--- a/boost/multiprecision/cpp_int/limits.hpp
+++ b/boost/multiprecision/cpp_int/limits.hpp
@@ -23,7 +23,7 @@ inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinB
{
// Bounded and signed.
typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> result_type;
- typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, Allocator>, ExpressionTemplates> ui_type;
+ typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MaxBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked>, ExpressionTemplates> ui_type;
static const result_type val = -result_type(~ui_type(0));
return val;
}
@@ -62,7 +62,7 @@ inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinB
{
// Bounded and signed.
typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> result_type;
- typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, Allocator>, ExpressionTemplates> ui_type;
+ typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MaxBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked>, ExpressionTemplates> ui_type;
static const result_type val = ~ui_type(0);
return val;
}
diff --git a/boost/multiprecision/cpp_int/multiply.hpp b/boost/multiprecision/cpp_int/multiply.hpp
index 88264c47be..afe1db7a9f 100644
--- a/boost/multiprecision/cpp_int/multiply.hpp
+++ b/boost/multiprecision/cpp_int/multiply.hpp
@@ -48,7 +48,7 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
{
unsigned i = result.size();
result.resize(i + 1, i + 1);
- if(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::variable || (result.size() > i))
+ if(result.size() > i)
result.limbs()[i] = static_cast<limb_type>(carry);
}
result.sign(a.sign());
@@ -157,7 +157,7 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
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(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::variable || (i + bs < result.size()))
+ if(i + bs < result.size())
pr[i + bs] = static_cast<limb_type>(carry);
carry = 0;
}
diff --git a/boost/multiprecision/debug_adaptor.hpp b/boost/multiprecision/debug_adaptor.hpp
index 1b69ba4aa6..1e395035f7 100644
--- a/boost/multiprecision/debug_adaptor.hpp
+++ b/boost/multiprecision/debug_adaptor.hpp
@@ -282,6 +282,7 @@ inline void eval_ldexp(debug_adaptor<Backend>& result, const debug_adaptor<Backe
template <class Backend, class Exp>
inline void eval_scalbn(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp exp)
{
+ using default_ops::eval_scalbn;
eval_scalbn(result.value(), arg.value(), exp);
result.update_view();
}
@@ -289,6 +290,7 @@ inline void eval_scalbn(debug_adaptor<Backend>& result, const debug_adaptor<Back
template <class Backend>
inline typename Backend::exponent_type eval_ilogb(const debug_adaptor<Backend>& arg)
{
+ using default_ops::eval_ilogb;
return eval_ilogb(arg.value());
}
@@ -456,12 +458,17 @@ NON_MEMBER_OP3(pow, "pow");
NON_MEMBER_OP3(atan2, "atan2");
template <class Backend>
+int eval_signbit(const debug_adaptor<Backend>& val)
+{
+ return eval_signbit(val.value());
+}
+
+template <class Backend>
std::size_t hash_value(const debug_adaptor<Backend>& val)
{
return hash_value(val.value());
}
-
} // namespace backends
using backends::debug_adaptor;
diff --git a/boost/multiprecision/detail/bitscan.hpp b/boost/multiprecision/detail/bitscan.hpp
index a21fd58651..21e8b8a3a9 100644
--- a/boost/multiprecision/detail/bitscan.hpp
+++ b/boost/multiprecision/detail/bitscan.hpp
@@ -8,6 +8,8 @@
#ifndef BOOST_MP_DETAIL_BITSCAN_HPP
#define BOOST_MP_DETAIL_BITSCAN_HPP
+#include <boost/detail/endian.hpp>
+
#if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
#include <intrin.h>
#endif
@@ -140,6 +142,36 @@ 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&)
+{
+ union { unsigned __int128 v; boost::uint64_t sv[2]; } val;
+ val.v = mask;
+#ifdef BOOST_LITTLE_ENDIAN
+ if(val.sv[1])
+ return find_msb(val.sv[1], mpl::int_<3>()) + 64;
+ return find_msb(val.sv[0], mpl::int_<3>());
+#else
+ if(val.sv[0])
+ return find_msb(val.sv[0], mpl::int_<3>()) + 64;
+ return find_msb(val.sv[1], mpl::int_<3>());
+#endif
+}
+BOOST_FORCEINLINE unsigned find_lsb(unsigned __int128 mask, mpl::int_<0> const&)
+{
+ union { unsigned __int128 v; boost::uint64_t sv[2]; } val;
+ val.v = mask;
+#ifdef BOOST_LITTLE_ENDIAN
+ if(val.sv[0] == 0)
+ return find_lsb(val.sv[1], mpl::int_<3>()) + 64;
+ return find_lsb(val.sv[0], mpl::int_<3>());
+#else
+ if(val.sv[1] == 0)
+ return find_lsb(val.sv[0], mpl::int_<3>()) + 64;
+ return find_lsb(val.sv[1], mpl::int_<3>());
+#endif
+}
+#endif
template <class Unsigned>
BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
diff --git a/boost/multiprecision/detail/default_ops.hpp b/boost/multiprecision/detail/default_ops.hpp
index fe8d5acd16..334db06a64 100644
--- a/boost/multiprecision/detail/default_ops.hpp
+++ b/boost/multiprecision/detail/default_ops.hpp
@@ -983,6 +983,25 @@ inline void eval_fmod(T& result, const T& a, const T& b)
result = temp;
return;
}
+ switch(eval_fpclassify(a))
+ {
+ case FP_ZERO:
+ result = a;
+ return;
+ case FP_INFINITE:
+ case FP_NAN:
+ result = std::numeric_limits<number<T> >::quiet_NaN().backend();
+ errno = EDOM;
+ return;
+ }
+ switch(eval_fpclassify(b))
+ {
+ case FP_ZERO:
+ case FP_NAN:
+ result = std::numeric_limits<number<T> >::quiet_NaN().backend();
+ errno = EDOM;
+ return;
+ }
T n;
eval_divide(result, a, b);
if(eval_get_sign(result) < 0)
@@ -1162,10 +1181,14 @@ template <class T>
inline void eval_trunc(T& result, const T& a)
{
BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
- int c = eval_fpclassify(a);
- if(c == (int)FP_NAN || c == (int)FP_INFINITE)
+ switch(eval_fpclassify(a))
{
- result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number<T>(a), number<T>(a), boost::math::policies::policy<>()).backend();
+ case FP_NAN:
+ errno = EDOM;
+ // fallthrough...
+ case FP_ZERO:
+ case FP_INFINITE:
+ result = a;
return;
}
if(eval_get_sign(a) < 0)
@@ -1212,12 +1235,17 @@ inline void eval_round(T& result, const T& a)
BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
typedef typename boost::multiprecision::detail::canonical<float, T>::type fp_type;
int c = eval_fpclassify(a);
- if((c == (int)FP_NAN) || (c == (int)FP_INFINITE))
+ if(c == (int)FP_NAN)
{
- result = boost::math::policies::raise_rounding_error("boost::multiprecision::round<%1%>(%1%)", 0, number<T>(a), number<T>(a), boost::math::policies::policy<>()).backend();
+ result = a;
+ errno = EDOM;
return;
}
- if(eval_get_sign(a) < 0)
+ if((c == FP_ZERO) || (c == (int)FP_INFINITE))
+ {
+ result = a;
+ }
+ else if(eval_get_sign(a) < 0)
{
eval_subtract(result, a, fp_type(0.5f));
eval_ceil(result, result);
@@ -1382,9 +1410,10 @@ void eval_integer_sqrt(B& s, B& r, const B& x)
return;
}
int g = eval_msb(x);
- if(g == 0)
+ if(g <= 1)
{
- r = ui_type(1);
+ s = ui_type(1);
+ eval_subtract(r, x, s);
return;
}
@@ -1408,6 +1437,7 @@ void eval_integer_sqrt(B& s, B& r, const B& x)
eval_bit_set(t, 2 * g);
if(t.compare(r) <= 0)
{
+ BOOST_ASSERT(g >= 0);
eval_bit_set(s, g);
eval_subtract(r, t);
if(eval_get_sign(r) == 0)
@@ -1448,7 +1478,11 @@ inline typename B::exponent_type eval_ilogb(const B& val)
switch(eval_fpclassify(val))
{
case FP_NAN:
- return (std::numeric_limits<typename B::exponent_type>::min)();
+#ifdef FP_ILOGBNAN
+ return FP_ILOGBNAN;
+#else
+ return (std::numeric_limits<typename B::exponent_type>::max)();
+#endif
case FP_INFINITE:
return (std::numeric_limits<typename B::exponent_type>::max)();
case FP_ZERO:
@@ -1458,9 +1492,30 @@ inline typename B::exponent_type eval_ilogb(const B& val)
eval_frexp(result, val, &e);
return e - 1;
}
+
+template <class T>
+int eval_signbit(const T& val);
+
template <class B>
inline void eval_logb(B& result, const B& val)
{
+ switch(eval_fpclassify(val))
+ {
+ case FP_NAN:
+ result = val;
+ errno = EDOM;
+ return;
+ case FP_ZERO:
+ result = std::numeric_limits<number<B> >::infinity().backend();
+ result.negate();
+ errno = ERANGE;
+ return;
+ case FP_INFINITE:
+ result = val;
+ if(eval_signbit(val))
+ result.negate();
+ return;
+ }
typedef typename boost::mpl::if_c<boost::is_same<boost::intmax_t, long>::value, boost::long_long_type, boost::intmax_t>::type max_t;
result = static_cast<max_t>(eval_ilogb(val));
}
@@ -1598,6 +1653,12 @@ inline void eval_rint(R& result, const T& a)
eval_nearbyint(result, a);
}
+template <class T>
+inline int eval_signbit(const T& val)
+{
+ return eval_get_sign(val) < 0 ? 1 : 0;
+}
+
//
// These functions are implemented in separate files, but expanded inline here,
// DO NOT CHANGE THE ORDER OF THESE INCLUDES:
@@ -1687,7 +1748,8 @@ inline int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::e
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
- return arg.sign() < 0;
+ using default_ops::eval_signbit;
+ return eval_signbit(arg.backend());
}
template <class tag, class A1, class A2, class A3, class A4>
inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
@@ -1837,7 +1899,14 @@ namespace multiprecision{
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
inline multiprecision::number<Backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
- return boost::math::lgamma(arg, c99_error_policy());
+ multiprecision::number<Backend, ExpressionTemplates> result;
+ result = boost::math::lgamma(arg, c99_error_policy());
+ if((boost::multiprecision::isnan)(result) && !(boost::multiprecision::isnan)(arg))
+ {
+ result = std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::infinity();
+ errno = ERANGE;
+ }
+ return result;
}
template <class tag, class A1, class A2, class A3, class A4>
inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
@@ -1848,6 +1917,11 @@ namespace multiprecision{
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
inline multiprecision::number<Backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
+ if((arg == 0) && std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::has_infinity)
+ {
+ errno = ERANGE;
+ return 1 / arg;
+ }
return boost::math::tgamma(arg, c99_error_policy());
}
template <class tag, class A1, class A2, class A3, class A4>
diff --git a/boost/multiprecision/detail/functions/pow.hpp b/boost/multiprecision/detail/functions/pow.hpp
index b244a18c8b..460658e034 100644
--- a/boost/multiprecision/detail/functions/pow.hpp
+++ b/boost/multiprecision/detail/functions/pow.hpp
@@ -208,11 +208,11 @@ void eval_exp(T& result, const T& x)
if(type == (int)FP_NAN)
{
result = x;
+ errno = EDOM;
return;
}
else if(type == (int)FP_INFINITE)
{
- result = x;
if(isneg)
result = ui_type(0u);
else
@@ -277,6 +277,17 @@ void eval_exp(T& result, const T& x)
detail::pow_imp(result, get_constant_e<T>(), ll, mpl::true_());
return;
}
+ else if(exp_series.compare(x) == 0)
+ {
+ // We have a value that has no fractional part, but is too large to fit
+ // in a long long, in this situation the code below will fail, so
+ // we're just going to assume that this will overflow:
+ 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 algorithm for exp has been taken from MPFUN.
// exp(t) = [ (1 + r + r^2/2! + r^3/3! + r^4/4! ...)^p2 ] * 2^n
@@ -326,6 +337,29 @@ void eval_log(T& result, const T& arg)
typedef typename T::exponent_type exp_type;
typedef typename boost::multiprecision::detail::canonical<exp_type, T>::type canonical_exp_type;
typedef typename mpl::front<typename T::float_types>::type fp_type;
+ int s = eval_signbit(arg);
+ switch(eval_fpclassify(arg))
+ {
+ case FP_NAN:
+ result = arg;
+ errno = EDOM;
+ return;
+ case FP_INFINITE:
+ if(s) break;
+ result = arg;
+ return;
+ case FP_ZERO:
+ result = std::numeric_limits<number<T> >::has_infinity ? std::numeric_limits<number<T> >::infinity().backend() : (std::numeric_limits<number<T> >::max)().backend();
+ result.negate();
+ errno = ERANGE;
+ return;
+ }
+ if(s)
+ {
+ result = std::numeric_limits<number<T> >::quiet_NaN().backend();
+ errno = EDOM;
+ return;
+ }
exp_type e;
T t;
@@ -427,19 +461,21 @@ inline void eval_pow(T& result, const T& x, const T& a)
return;
}
- if(a.compare(si_type(1)) == 0)
+ if((a.compare(si_type(1)) == 0) || (x.compare(si_type(1)) == 0))
{
result = x;
return;
}
+ if(a.compare(si_type(0)) == 0)
+ {
+ result = si_type(1);
+ return;
+ }
int type = eval_fpclassify(x);
switch(type)
{
- case FP_INFINITE:
- result = x;
- return;
case FP_ZERO:
switch(eval_fpclassify(a))
{
@@ -449,13 +485,58 @@ inline void eval_pow(T& result, const T& x, const T& a)
case FP_NAN:
result = a;
break;
+ case FP_NORMAL:
+ {
+ // Need to check for a an odd integer as a special case:
+ try
+ {
+ typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type i;
+ eval_convert_to(&i, a);
+ if(a.compare(i) == 0)
+ {
+ if(eval_signbit(a))
+ {
+ if(i & 1)
+ {
+ result = std::numeric_limits<number<T> >::infinity().backend();
+ if(eval_signbit(x))
+ result.negate();
+ errno = ERANGE;
+ }
+ else
+ {
+ result = std::numeric_limits<number<T> >::infinity().backend();
+ errno = ERANGE;
+ }
+ }
+ else if(i & 1)
+ {
+ result = x;
+ }
+ else
+ result = si_type(0);
+ return;
+ }
+ }
+ catch(const std::exception&)
+ {
+ // fallthrough..
+ }
+ }
default:
- result = x;
+ if(eval_signbit(a))
+ {
+ result = std::numeric_limits<number<T> >::infinity().backend();
+ errno = ERANGE;
+ }
+ else
+ result = x;
break;
}
return;
case FP_NAN:
result = x;
+ errno = ERANGE;
return;
default: ;
}
@@ -478,6 +559,16 @@ inline void eval_pow(T& result, const T& x, const T& a)
}
typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type an;
+ typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type max_an =
+ std::numeric_limits<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>::is_specialized ?
+ (std::numeric_limits<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>::max)() :
+ static_cast<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>(1) << (sizeof(typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type) * CHAR_BIT - 2);
+ typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type min_an =
+ std::numeric_limits<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>::is_specialized ?
+ (std::numeric_limits<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>::min)() :
+ -min_an;
+
+
T fa;
#ifndef BOOST_NO_EXCEPTIONS
try
@@ -521,8 +612,33 @@ inline void eval_pow(T& result, const T& x, const T& a)
// conversion failed, just fall through, value is not an integer.
}
#endif
- if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ eval_floor(result, a);
+ // -1^INF is a special case in C99:
+ if((x.compare(si_type(-1)) == 0) && (eval_fpclassify(a) == FP_INFINITE))
+ {
+ result = si_type(1);
+ }
+ else if(a.compare(result) == 0)
+ {
+ // exponent is so large we have no fractional part:
+ if(x.compare(si_type(-1)) < 0)
+ {
+ result = std::numeric_limits<number<T, et_on> >::infinity().backend();
+ }
+ else
+ {
+ result = si_type(0);
+ }
+ }
+ else if(type == FP_INFINITE)
+ {
+ result = std::numeric_limits<number<T, et_on> >::infinity().backend();
+ }
+ else if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ {
result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
+ errno = EDOM;
+ }
else
{
BOOST_THROW_EXCEPTION(std::domain_error("Result of pow is undefined or non-real and there is no NaN for this number type."));
@@ -534,7 +650,7 @@ inline void eval_pow(T& result, const T& x, const T& a)
eval_subtract(da, a, an);
- if((x.compare(fp_type(0.5)) >= 0) && (x.compare(fp_type(0.9)) < 0))
+ if((x.compare(fp_type(0.5)) >= 0) && (x.compare(fp_type(0.9)) < 0) && (an < max_an) && (an > min_an))
{
if(a.compare(fp_type(1e-5f)) <= 0)
{
@@ -618,14 +734,20 @@ void eval_exp2(T& result, const T& arg)
// Check for pure-integer arguments which can be either signed or unsigned.
typename boost::multiprecision::detail::canonical<typename T::exponent_type, T>::type i;
T temp;
- eval_trunc(temp, arg);
- eval_convert_to(&i, temp);
- if(arg.compare(i) == 0)
- {
- temp = static_cast<typename mpl::front<typename T::unsigned_types>::type>(1u);
- eval_ldexp(result, temp, i);
- return;
+ try {
+ eval_trunc(temp, arg);
+ eval_convert_to(&i, temp);
+ if(arg.compare(i) == 0)
+ {
+ temp = static_cast<typename mpl::front<typename T::unsigned_types>::type>(1u);
+ eval_ldexp(result, temp, i);
+ return;
+ }
}
+ catch(const boost::math::rounding_error&)
+ { /* Fallthrough */ }
+ catch(const std::runtime_error&)
+ { /* Fallthrough */ }
temp = static_cast<typename mpl::front<typename T::unsigned_types>::type>(2u);
eval_pow(result, temp, arg);
@@ -669,6 +791,8 @@ namespace detail{
switch(eval_fpclassify(x))
{
case FP_NAN:
+ errno = EDOM;
+ // fallthrough...
case FP_INFINITE:
if(p_sinh)
*p_sinh = x;
@@ -695,6 +819,8 @@ namespace detail{
T e_px, e_mx;
eval_exp(e_px, x);
eval_divide(e_mx, ui_type(1), e_px);
+ if(eval_signbit(e_mx) != eval_signbit(e_px))
+ e_mx.negate(); // Handles lack of signed zero in some types
if(p_sinh)
{
@@ -742,6 +868,14 @@ inline void eval_tanh(T& result, const T& x)
BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The tanh function is only valid for floating point types.");
T c;
detail::sinhcosh(x, &result, &c);
+ if((eval_fpclassify(result) == FP_INFINITE) && (eval_fpclassify(c) == FP_INFINITE))
+ {
+ bool s = eval_signbit(result) != eval_signbit(c);
+ result = static_cast<typename mpl::front<typename T::unsigned_types>::type>(1u);
+ if(s)
+ result.negate();
+ return;
+ }
eval_divide(result, c);
}
diff --git a/boost/multiprecision/detail/functions/trig.hpp b/boost/multiprecision/detail/functions/trig.hpp
index c84a639418..319b708b0c 100644
--- a/boost/multiprecision/detail/functions/trig.hpp
+++ b/boost/multiprecision/detail/functions/trig.hpp
@@ -91,12 +91,15 @@ void eval_sin(T& result, const T& x)
case FP_INFINITE:
case FP_NAN:
if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ {
result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
+ errno = EDOM;
+ }
else
BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
return;
case FP_ZERO:
- result = ui_type(0);
+ result = x;
return;
default: ;
}
@@ -238,7 +241,10 @@ void eval_cos(T& result, const T& x)
case FP_INFINITE:
case FP_NAN:
if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ {
result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
+ errno = EDOM;
+ }
else
BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
return;
@@ -422,12 +428,15 @@ void eval_asin(T& result, const T& x)
case FP_NAN:
case FP_INFINITE:
if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ {
result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
+ errno = EDOM;
+ }
else
BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
return;
case FP_ZERO:
- result = ui_type(0);
+ result = x;
return;
default: ;
}
@@ -442,7 +451,10 @@ void eval_asin(T& result, const T& x)
if(c > 0)
{
if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ {
result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
+ errno = EDOM;
+ }
else
BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
return;
@@ -515,10 +527,8 @@ void eval_asin(T& result, const T& x)
eval_divide(sine, cosine);
eval_subtract(result, sine);
current_precision = eval_ilogb(sine);
-#ifdef FP_ILOGB0
- if(current_precision == FP_ILOGB0)
+ if(current_precision <= (std::numeric_limits<typename T::exponent_type>::min)() + 1)
break;
-#endif
}
if(b_neg)
result.negate();
@@ -535,7 +545,10 @@ inline void eval_acos(T& result, const T& x)
case FP_NAN:
case FP_INFINITE:
if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ {
result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
+ errno = EDOM;
+ }
else
BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
return;
@@ -551,7 +564,10 @@ inline void eval_acos(T& result, const T& x)
if(c > 0)
{
if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+ {
result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
+ errno = EDOM;
+ }
else
BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
return;
@@ -584,9 +600,10 @@ void eval_atan(T& result, const T& x)
{
case FP_NAN:
result = x;
+ errno = EDOM;
return;
case FP_ZERO:
- result = ui_type(0);
+ result = x;
return;
case FP_INFINITE:
if(eval_get_sign(x) < 0)
@@ -662,10 +679,8 @@ void eval_atan(T& result, const T& x)
eval_multiply(s, t, c);
eval_add(result, s);
current_precision = eval_ilogb(s);
-#ifdef FP_ILOGB0
- if(current_precision == FP_ILOGB0)
+ if(current_precision <= (std::numeric_limits<typename T::exponent_type>::min)() + 1)
break;
-#endif
}
if(b_neg)
result.negate();
@@ -694,24 +709,41 @@ void eval_atan2(T& result, const T& y, const T& x)
{
case FP_NAN:
result = y;
+ errno = EDOM;
return;
case FP_ZERO:
{
- int c = eval_get_sign(x);
- if(c < 0)
+ if(eval_signbit(x))
+ {
result = get_constant_pi<T>();
- else if(c >= 0)
- result = ui_type(0); // Note we allow atan2(0,0) to be zero, even though it's mathematically undefined
+ if(eval_signbit(y))
+ result.negate();
+ }
+ else
+ {
+ result = y; // Note we allow atan2(0,0) to be +-zero, even though it's mathematically undefined
+ }
return;
}
case FP_INFINITE:
{
if(eval_fpclassify(x) == FP_INFINITE)
{
- if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
- result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
+ if(eval_signbit(x))
+ {
+ // 3Pi/4
+ eval_ldexp(result, get_constant_pi<T>(), -2);
+ eval_subtract(result, get_constant_pi<T>());
+ if(eval_get_sign(y) >= 0)
+ result.negate();
+ }
else
- BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+ {
+ // Pi/4
+ eval_ldexp(result, get_constant_pi<T>(), -2);
+ if(eval_get_sign(y) < 0)
+ result.negate();
+ }
}
else
{
@@ -727,6 +759,7 @@ void eval_atan2(T& result, const T& y, const T& x)
{
case FP_NAN:
result = x;
+ errno = EDOM;
return;
case FP_ZERO:
{
diff --git a/boost/multiprecision/float128.hpp b/boost/multiprecision/float128.hpp
index 702d488cd6..8de3af6519 100644
--- a/boost/multiprecision/float128.hpp
+++ b/boost/multiprecision/float128.hpp
@@ -399,15 +399,6 @@ inline void eval_fabs(float128_backend& result, const float128_backend& arg)
inline void eval_trunc(float128_backend& result, const float128_backend& arg)
{
- if(isnanq(arg.value()) || isinfq(arg.value()))
- {
- result = boost::math::policies::raise_rounding_error(
- "boost::multiprecision::trunc<%1%>(%1%)", 0,
- number<float128_backend, et_off>(arg),
- number<float128_backend, et_off>(arg),
- boost::math::policies::policy<>()).backend();
- return;
- }
result.value() = truncq(arg.value());
}
/*
@@ -494,6 +485,11 @@ inline void eval_multiply_add(float128_backend& result, const float128_backend&
result.value() = fmaq(a.value(), b.value(), c.value());
}
+inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const float128_backend& arg)
+{
+ return ::signbitq(arg.value());
+}
+
inline std::size_t hash_value(const float128_backend& val)
{
return boost::hash_value(static_cast<double>(val.value()));
@@ -553,12 +549,6 @@ inline std::size_t hash_value(const float128_backend& val)
}
template <multiprecision::expression_template_option ExpressionTemplates>
- inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& arg)
- {
- return ::signbitq(arg.backend().value());
- }
-
- template <multiprecision::expression_template_option ExpressionTemplates>
inline boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& b)
{
return ::copysignq(a.backend().value(), b.backend().value());
diff --git a/boost/multiprecision/logged_adaptor.hpp b/boost/multiprecision/logged_adaptor.hpp
index 2f916dd101..7cb33ee57a 100644
--- a/boost/multiprecision/logged_adaptor.hpp
+++ b/boost/multiprecision/logged_adaptor.hpp
@@ -507,6 +507,13 @@ NON_MEMBER_OP3(pow, "pow");
NON_MEMBER_OP3(atan2, "atan2");
template <class Backend>
+int eval_signbit(const logged_adaptor<Backend>& val)
+{
+ using default_ops::eval_signbit;
+ return eval_signbit(val.value());
+}
+
+template <class Backend>
std::size_t hash_value(const logged_adaptor<Backend>& val)
{
return hash_value(val.value());
diff --git a/boost/multiprecision/mpfi.hpp b/boost/multiprecision/mpfi.hpp
index b863e31352..a06e4a39d4 100644
--- a/boost/multiprecision/mpfi.hpp
+++ b/boost/multiprecision/mpfi.hpp
@@ -1042,7 +1042,7 @@ inline std::size_t hash_value(const mpfi_float_backend<Digits10>& val)
std::size_t len = val.left_data()[0]._mpfr_prec / mp_bits_per_limb;
if(val.left_data()[0]._mpfr_prec % mp_bits_per_limb)
++len;
- for(int i = 0; i < len; ++i)
+ for(std::size_t i = 0; i < len; ++i)
boost::hash_combine(result, val.left_data()[0]._mpfr_d[i]);
boost::hash_combine(result, val.left_data()[0]._mpfr_exp);
boost::hash_combine(result, val.left_data()[0]._mpfr_sign);
@@ -1050,7 +1050,7 @@ inline std::size_t hash_value(const mpfi_float_backend<Digits10>& val)
len = val.right_data()[0]._mpfr_prec / mp_bits_per_limb;
if(val.right_data()[0]._mpfr_prec % mp_bits_per_limb)
++len;
- for(int i = 0; i < len; ++i)
+ for(std::size_t i = 0; i < len; ++i)
boost::hash_combine(result, val.right_data()[0]._mpfr_d[i]);
boost::hash_combine(result, val.right_data()[0]._mpfr_exp);
boost::hash_combine(result, val.right_data()[0]._mpfr_sign);
@@ -1420,7 +1420,7 @@ struct constant_pi<boost::multiprecision::number<boost::multiprecision::mpfi_flo
{
typedef boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result_type;
template<int N>
- static inline result_type const& get(const mpl::int_<N>&)
+ static inline const result_type& get(const mpl::int_<N>&)
{
mpfi_initializer<result_type>::force_instantiate();
static result_type result;
@@ -1444,7 +1444,7 @@ struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfi
{
typedef boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result_type;
template<int N>
- static inline result_type get(const mpl::int_<N>&)
+ static inline const result_type& get(const mpl::int_<N>&)
{
mpfi_initializer<result_type>::force_instantiate();
static result_type result;
diff --git a/boost/multiprecision/mpfr.hpp b/boost/multiprecision/mpfr.hpp
index 440517ff86..2759a8a8de 100644
--- a/boost/multiprecision/mpfr.hpp
+++ b/boost/multiprecision/mpfr.hpp
@@ -1286,11 +1286,6 @@ inline void eval_floor(mpfr_float_backend<Digits10, AllocateType>& result, const
template <unsigned Digits10, mpfr_allocation_type AllocateType>
inline void eval_trunc(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
{
- if(0 == mpfr_number_p(val.data()))
- {
- result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number<mpfr_float_backend<Digits10, AllocateType> >(val), number<mpfr_float_backend<Digits10, AllocateType> >(val), boost::math::policies::policy<>()).backend();
- return;
- }
mpfr_trunc(result.data(), val.data());
}
template <unsigned Digits10, mpfr_allocation_type AllocateType>
@@ -1327,7 +1322,12 @@ inline int eval_fpclassify(const mpfr_float_backend<Digits10, AllocateType>& val
template <unsigned Digits10, mpfr_allocation_type AllocateType>
inline void eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const mpfr_float_backend<Digits10, AllocateType>& e)
{
- mpfr_pow(result.data(), b.data(), e.data(), GMP_RNDN);
+ if(mpfr_zero_p(b.data()) && mpfr_integer_p(e.data()) && (mpfr_signbit(e.data()) == 0) && mpfr_fits_ulong_p(e.data(), GMP_RNDN) && (mpfr_get_ui(e.data(), GMP_RNDN) & 1))
+ {
+ mpfr_set(result.data(), b.data(), GMP_RNDN);
+ }
+ else
+ mpfr_pow(result.data(), b.data(), e.data(), GMP_RNDN);
}
#ifdef BOOST_MSVC
@@ -1505,13 +1505,19 @@ inline void eval_multiply_subtract(mpfr_float_backend<Digits10, AllocateType>& r
}
template <unsigned Digits10, mpfr_allocation_type AllocateType>
+inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const mpfr_float_backend<Digits10, AllocateType>& arg)
+{
+ return (arg.data()[0]._mpfr_sign < 0) ? 1 : 0;
+}
+
+template <unsigned Digits10, mpfr_allocation_type AllocateType>
inline std::size_t hash_value(const mpfr_float_backend<Digits10, AllocateType>& val)
{
std::size_t result = 0;
std::size_t len = val.data()[0]._mpfr_prec / mp_bits_per_limb;
if(val.data()[0]._mpfr_prec % mp_bits_per_limb)
++len;
- for(int i = 0; i < len; ++i)
+ for(std::size_t i = 0; i < len; ++i)
boost::hash_combine(result, val.data()[0]._mpfr_d[i]);
boost::hash_combine(result, val.data()[0]._mpfr_exp);
boost::hash_combine(result, val.data()[0]._mpfr_sign);
@@ -1546,24 +1552,12 @@ typedef number<mpfr_float_backend<50, allocate_stack> > static_mpfr_float_50;
typedef number<mpfr_float_backend<100, allocate_stack> > static_mpfr_float_100;
template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
-inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
-{
- return (arg.backend().data()[0]._mpfr_sign < 0) ? 1 : 0;
-}
-
-template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& b)
{
return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(-a) : a;
}
template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
-inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
-{
- return (arg.backend().value().data()[0]._mpfr_sign < 0) ? 1 : 0;
-}
-
-template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& b)
{
return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>(-a) : a;
diff --git a/boost/multiprecision/number.hpp b/boost/multiprecision/number.hpp
index aaf6532e13..c3819dc561 100644
--- a/boost/multiprecision/number.hpp
+++ b/boost/multiprecision/number.hpp
@@ -1732,7 +1732,7 @@ inline std::string read_string_while(std::istream& is, std::string const& permit
for(;; c = is.rdbuf()->snextc())
if(std::istream::traits_type::eq_int_type(std::istream::traits_type::eof(), c))
- { // end of file:
+ { // end of file:
state |= std::ios_base::eofbit;
break;
}
@@ -1743,7 +1743,7 @@ inline std::string read_string_while(std::istream& is, std::string const& permit
break;
}
else
- {
+ {
result.append(1, std::istream::traits_type::to_char_type(c));
}
}
@@ -1856,78 +1856,6 @@ inline std::istream& operator >> (std::istream& is, rational<multiprecision::num
return is;
}
-template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
-typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator == (const rational<multiprecision::number<T, ExpressionTemplates> >& a, const Arithmetic& b)
-{
- return a == multiprecision::number<T, ExpressionTemplates>(b);
-}
-
-template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
-typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator == (const Arithmetic& b, const rational<multiprecision::number<T, ExpressionTemplates> >& a)
-{
- return a == multiprecision::number<T, ExpressionTemplates>(b);
-}
-
-template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
-typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator != (const rational<multiprecision::number<T, ExpressionTemplates> >& a, const Arithmetic& b)
-{
- return a != multiprecision::number<T, ExpressionTemplates>(b);
-}
-
-template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
-typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator != (const Arithmetic& b, const rational<multiprecision::number<T, ExpressionTemplates> >& a)
-{
- return a != multiprecision::number<T, ExpressionTemplates>(b);
-}
-
-template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
-typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator < (const rational<multiprecision::number<T, ExpressionTemplates> >& a, const Arithmetic& b)
-{
- return a < multiprecision::number<T, ExpressionTemplates>(b);
-}
-
-template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
-typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator < (const Arithmetic& b, const rational<multiprecision::number<T, ExpressionTemplates> >& a)
-{
- return a > multiprecision::number<T, ExpressionTemplates>(b);
-}
-
-template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
-typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator <= (const rational<multiprecision::number<T, ExpressionTemplates> >& a, const Arithmetic& b)
-{
- return a <= multiprecision::number<T, ExpressionTemplates>(b);
-}
-
-template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
-typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator <= (const Arithmetic& b, const rational<multiprecision::number<T, ExpressionTemplates> >& a)
-{
- return a >= multiprecision::number<T, ExpressionTemplates>(b);
-}
-
-template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
-typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator > (const rational<multiprecision::number<T, ExpressionTemplates> >& a, const Arithmetic& b)
-{
- return a > multiprecision::number<T, ExpressionTemplates>(b);
-}
-
-template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
-typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator > (const Arithmetic& b, const rational<multiprecision::number<T, ExpressionTemplates> >& a)
-{
- return a < multiprecision::number<T, ExpressionTemplates>(b);
-}
-
-template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
-typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator >= (const rational<multiprecision::number<T, ExpressionTemplates> >& a, const Arithmetic& b)
-{
- return a >= multiprecision::number<T, ExpressionTemplates>(b);
-}
-
-template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
-typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator >= (const Arithmetic& b, const rational<multiprecision::number<T, ExpressionTemplates> >& a)
-{
- return a <= multiprecision::number<T, ExpressionTemplates>(b);
-}
-
template <class T, multiprecision::expression_template_option ExpressionTemplates>
inline multiprecision::number<T, ExpressionTemplates> numerator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
{
diff --git a/boost/numeric/interval/hw_rounding.hpp b/boost/numeric/interval/hw_rounding.hpp
index d0062567f8..574b2433a1 100644
--- a/boost/numeric/interval/hw_rounding.hpp
+++ b/boost/numeric/interval/hw_rounding.hpp
@@ -1,6 +1,6 @@
/* Boost interval/hw_rounding.hpp template implementation file
*
- * 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.
@@ -21,6 +21,8 @@
# include <boost/numeric/interval/detail/c99_rounding_control.hpp>
#elif defined(__i386__) || defined(_M_IX86) || defined(__BORLANDC__) || defined(_M_X64)
# include <boost/numeric/interval/detail/x86_rounding_control.hpp>
+#elif defined(__i386) && defined(__SUNPRO_CC)
+# include <boost/numeric/interval/detail/x86_rounding_control.hpp>
#elif defined(powerpc) || defined(__powerpc__) || defined(__ppc__)
# include <boost/numeric/interval/detail/ppc_rounding_control.hpp>
#elif defined(sparc) || defined(__sparc__)
diff --git a/boost/pool/pool_alloc.hpp b/boost/pool/pool_alloc.hpp
index fe6fa5ff9b..4233ca66a6 100644
--- a/boost/pool/pool_alloc.hpp
+++ b/boost/pool/pool_alloc.hpp
@@ -79,6 +79,14 @@ STLport (with any compiler), ver. 4.0 and earlier.
#include <boost/detail/workaround.hpp>
+// C++11 features detection
+#include <boost/config.hpp>
+
+// std::forward
+#ifdef BOOST_HAS_VARIADIC_TMPL
+#include <utility>
+#endif
+
#ifdef BOOST_POOL_INSTRUMENT
#include <iostream>
#include <iomanip>
@@ -206,8 +214,16 @@ class pool_allocator
{ return &s; }
static size_type max_size()
{ return (std::numeric_limits<size_type>::max)(); }
+
+#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
+ template <typename U, typename... Args>
+ static void construct(U* ptr, Args&&... args)
+ { new (ptr) U(std::forward<Args>(args)...); }
+#else
static void construct(const pointer ptr, const value_type & t)
{ new (ptr) T(t); }
+#endif
+
static void destroy(const pointer ptr)
{
ptr->~T();
@@ -395,8 +411,16 @@ class fast_pool_allocator
{ return &s; }
static size_type max_size()
{ return (std::numeric_limits<size_type>::max)(); }
+
+#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
+ template <typename U, typename... Args>
+ void construct(U* ptr, Args&&... args)
+ { new (ptr) U(std::forward<Args>(args)...); }
+#else
void construct(const pointer ptr, const value_type & t)
{ new (ptr) T(t); }
+#endif
+
void destroy(const pointer ptr)
{ //! Destroy ptr using destructor.
ptr->~T();
diff --git a/boost/predef/compiler/intel.h b/boost/predef/compiler/intel.h
index 65bde6778a..3bd76fee08 100644
--- a/boost/predef/compiler/intel.h
+++ b/boost/predef/compiler/intel.h
@@ -25,7 +25,8 @@ Version number available as major, minor, and patch.
[[`__ICC`] [__predef_detection__]]
[[`__ECC`] [__predef_detection__]]
- [[`__INTEL_COMPILER`] [V.R.P]]
+ [[`__INTEL_COMPILER`] [V.R]]
+ [[`__INTEL_COMPILER` and `__INTEL_COMPILER_UPDATE`] [V.R.P]]
]
*/
@@ -33,8 +34,14 @@ Version number available as major, minor, and patch.
#if defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || \
defined(__ECC)
+# if !defined(BOOST_COMP_INTEL_DETECTION) && defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE)
+# define BOOST_COMP_INTEL_DETECTION BOOST_VERSION_NUMBER( \
+ BOOST_VERSION_NUMBER_MAJOR(BOOST_PREDEF_MAKE_10_VVRR(__INTEL_COMPILER)), \
+ BOOST_VERSION_NUMBER_MINOR(BOOST_PREDEF_MAKE_10_VVRR(__INTEL_COMPILER)), \
+ __INTEL_COMPILER_UPDATE)
+# endif
# if !defined(BOOST_COMP_INTEL_DETECTION) && defined(__INTEL_COMPILER)
-# define BOOST_COMP_INTEL_DETECTION BOOST_PREDEF_MAKE_10_VRP(__INTEL_COMPILER)
+# define BOOST_COMP_INTEL_DETECTION BOOST_PREDEF_MAKE_10_VVRR(__INTEL_COMPILER)
# endif
# if !defined(BOOST_COMP_INTEL_DETECTION)
# define BOOST_COMP_INTEL_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
diff --git a/boost/predef/compiler/visualc.h b/boost/predef/compiler/visualc.h
index 9481d9d9fd..f81e61ed52 100644
--- a/boost/predef/compiler/visualc.h
+++ b/boost/predef/compiler/visualc.h
@@ -29,6 +29,10 @@ Version number available as major, minor, and patch.
[[`_MSC_FULL_VER`] [V.R.P]]
[[`_MSC_VER`] [V.R.0]]
]
+
+[note Release of Visual Studio after 2015 will no longer be identified
+by Boost Predef as the marketing version number. Instead we use the
+compiler version number directly, i.e. the _MSC_VER number.]
*/
#define BOOST_COMP_MSVC BOOST_VERSION_NUMBER_NOT_AVAILABLE
@@ -53,8 +57,18 @@ Version number available as major, minor, and patch.
means that the compiler and VS product versions are no longer
in sync. Hence we need to use different formulas for
mapping from MSC version to VS product version.
+
+ VS2017 is a total nightmare when it comes to version numbers.
+ Hence to avoid arguments relating to that both present and
+ future.. Any version after VS2015 will use solely the compiler
+ version, i.e. cl.exe, as the version number here.
*/
-# if (_MSC_VER >= 1900)
+# if (_MSC_VER > 1900)
+# define BOOST_COMP_MSVC_DETECTION BOOST_VERSION_NUMBER(\
+ _MSC_VER/100,\
+ _MSC_VER%100,\
+ BOOST_COMP_MSVC_BUILD)
+# elif (_MSC_VER >= 1900)
# define BOOST_COMP_MSVC_DETECTION BOOST_VERSION_NUMBER(\
_MSC_VER/100-5,\
_MSC_VER%100,\
diff --git a/boost/predef/version.h b/boost/predef/version.h
index 8745c94976..ebd2b4fd9f 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,4,1)
+#define BOOST_PREDEF_VERSION BOOST_VERSION_NUMBER(1,5,0)
#endif
diff --git a/boost/predef/version_number.h b/boost/predef/version_number.h
index 3903a36b70..44942709c7 100644
--- a/boost/predef/version_number.h
+++ b/boost/predef/version_number.h
@@ -1,5 +1,5 @@
/*
-Copyright Rene Rivera 2005, 2008-2013
+Copyright Rene Rivera 2005-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)
@@ -50,4 +50,23 @@ Defines standard version numbers, with these properties:
#define BOOST_VERSION_NUMBER_NOT_AVAILABLE \
BOOST_VERSION_NUMBER_ZERO
+/*`
+``
+BOOST_VERSION_NUMBER_MAJOR(N), BOOST_VERSION_NUMBER_MINOR(N), BOOST_VERSION_NUMBER_PATCH(N)
+``
+
+The macros extract the major, minor, and patch portion from a well formed
+version number resulting in a preprocessor expression in the range of
+\[0,99\] or \[0,99999\] for the major and minor, or patch numbers
+respectively.
+*/
+#define BOOST_VERSION_NUMBER_MAJOR(N) \
+ ( ((N)/10000000)%100 )
+
+#define BOOST_VERSION_NUMBER_MINOR(N) \
+ ( ((N)/100000)%100 )
+
+#define BOOST_VERSION_NUMBER_PATCH(N) \
+ ( (N)%100000 )
+
#endif
diff --git a/boost/preprocessor/cat.hpp b/boost/preprocessor/cat.hpp
index 5e52850d48..52a389270c 100644
--- a/boost/preprocessor/cat.hpp
+++ b/boost/preprocessor/cat.hpp
@@ -25,7 +25,7 @@
# define BOOST_PP_CAT_OO(par) BOOST_PP_CAT_I ## par
# endif
#
-# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# if (~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1700)
# define BOOST_PP_CAT_I(a, b) a ## b
# else
# define BOOST_PP_CAT_I(a, b) BOOST_PP_CAT_II(~, a ## b)
diff --git a/boost/preprocessor/config/config.hpp b/boost/preprocessor/config/config.hpp
index 8be0e47545..4801903141 100644
--- a/boost/preprocessor/config/config.hpp
+++ b/boost/preprocessor/config/config.hpp
@@ -32,7 +32,7 @@
# elif defined(__MWERKS__) && __MWERKS__ >= 0x3200
# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_STRICT())
# elif defined(__EDG__) || defined(__EDG_VERSION__)
-# if defined(_MSC_VER) && (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())
@@ -45,7 +45,7 @@
# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_STRICT())
# elif defined(__BORLANDC__) || defined(__IBMC__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_BCC())
-# elif defined(_MSC_VER) && !defined(__clang__)
+# elif defined(_MSC_VER)
# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_MSVC())
# else
# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_STRICT())
@@ -75,8 +75,8 @@
# /* 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
-# /* VC++ (C/C++) */
-# elif defined _MSC_VER && _MSC_VER >= 1400 && (!defined __EDG__ || defined(__INTELLISENSE__)) && !defined __clang__
+# /* 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)
# 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(__INTELLISENSE__) || !(defined __EDG__ || defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __clang__ || 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/preprocessor/seq/detail/binary_transform.hpp b/boost/preprocessor/seq/detail/binary_transform.hpp
index 70897b09cf..08b5f9de4d 100644
--- a/boost/preprocessor/seq/detail/binary_transform.hpp
+++ b/boost/preprocessor/seq/detail/binary_transform.hpp
@@ -30,14 +30,13 @@
# endif
# if BOOST_PP_VARIADICS
# if BOOST_PP_VARIADICS_MSVC
-# define BOOST_PP_SEQ_BINARY_TRANSFORM_GET_REM(...) \
- BOOST_PP_VARIADIC_IS_SINGLE_RETURN(BOOST_PP_REM_CAT,BOOST_PP_REM,__VA_ARGS__) \
- /**/
+# define BOOST_PP_SEQ_BINARY_TRANSFORM_REM(data) data
+# define BOOST_PP_SEQ_BINARY_TRANSFORM_A(...) (BOOST_PP_SEQ_BINARY_TRANSFORM_REM, __VA_ARGS__)() BOOST_PP_SEQ_BINARY_TRANSFORM_B
+# define BOOST_PP_SEQ_BINARY_TRANSFORM_B(...) (BOOST_PP_SEQ_BINARY_TRANSFORM_REM, __VA_ARGS__)() BOOST_PP_SEQ_BINARY_TRANSFORM_A
# else
-# define BOOST_PP_SEQ_BINARY_TRANSFORM_GET_REM(...) BOOST_PP_REM
+# define BOOST_PP_SEQ_BINARY_TRANSFORM_A(...) (BOOST_PP_REM, __VA_ARGS__)() BOOST_PP_SEQ_BINARY_TRANSFORM_B
+# define BOOST_PP_SEQ_BINARY_TRANSFORM_B(...) (BOOST_PP_REM, __VA_ARGS__)() BOOST_PP_SEQ_BINARY_TRANSFORM_A
# endif
-# define BOOST_PP_SEQ_BINARY_TRANSFORM_A(...) (BOOST_PP_SEQ_BINARY_TRANSFORM_GET_REM(__VA_ARGS__), __VA_ARGS__)() BOOST_PP_SEQ_BINARY_TRANSFORM_B
-# define BOOST_PP_SEQ_BINARY_TRANSFORM_B(...) (BOOST_PP_SEQ_BINARY_TRANSFORM_GET_REM(__VA_ARGS__), __VA_ARGS__)() BOOST_PP_SEQ_BINARY_TRANSFORM_A
# else
# define BOOST_PP_SEQ_BINARY_TRANSFORM_A(e) (BOOST_PP_REM, e)() BOOST_PP_SEQ_BINARY_TRANSFORM_B
# define BOOST_PP_SEQ_BINARY_TRANSFORM_B(e) (BOOST_PP_REM, e)() BOOST_PP_SEQ_BINARY_TRANSFORM_A
diff --git a/boost/preprocessor/seq/detail/to_list_msvc.hpp b/boost/preprocessor/seq/detail/to_list_msvc.hpp
new file mode 100644
index 0000000000..2599c0014a
--- /dev/null
+++ b/boost/preprocessor/seq/detail/to_list_msvc.hpp
@@ -0,0 +1,55 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Edward Diener 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 for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_SEQ_DETAIL_TO_LIST_MSVC_HPP
+# define BOOST_PREPROCESSOR_SEQ_DETAIL_TO_LIST_MSVC_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/arithmetic/dec.hpp>
+# include <boost/preprocessor/control/while.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+#
+# define BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC_STATE_RESULT(state) \
+ BOOST_PP_TUPLE_ELEM(2, 0, state) \
+/**/
+# define BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC_STATE_SIZE(state) \
+ BOOST_PP_TUPLE_ELEM(2, 1, state) \
+/**/
+# define BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC_PRED(d,state) \
+ BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC_STATE_SIZE(state) \
+/**/
+# define BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC_OP(d,state) \
+ ( \
+ BOOST_PP_CAT(BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC_STATE_RESULT(state),), \
+ BOOST_PP_DEC(BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC_STATE_SIZE(state)) \
+ ) \
+/**/
+#
+# /* BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC */
+#
+# define BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC(result,seqsize) \
+ BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC_STATE_RESULT \
+ ( \
+ BOOST_PP_WHILE \
+ ( \
+ BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC_PRED, \
+ BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC_OP, \
+ (result,seqsize) \
+ ) \
+ ) \
+/**/
+# endif // BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+#
+# endif // BOOST_PREPROCESSOR_SEQ_DETAIL_TO_LIST_MSVC_HPP
diff --git a/boost/preprocessor/seq/to_list.hpp b/boost/preprocessor/seq/to_list.hpp
index fa0421bcc8..ed8948dbd4 100644
--- a/boost/preprocessor/seq/to_list.hpp
+++ b/boost/preprocessor/seq/to_list.hpp
@@ -19,7 +19,19 @@
#
# /* BOOST_PP_SEQ_TO_LIST */
#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# include <boost/preprocessor/seq/size.hpp>
+# include <boost/preprocessor/seq/detail/to_list_msvc.hpp>
+# define BOOST_PP_SEQ_TO_LIST(seq) \
+ BOOST_PP_SEQ_DETAIL_TO_LIST_MSVC \
+ ( \
+ BOOST_PP_SEQ_TO_LIST_I(BOOST_PP_SEQ_BINARY_TRANSFORM(seq)), \
+ BOOST_PP_SEQ_SIZE(seq) \
+ ) \
+/**/
+# else
# define BOOST_PP_SEQ_TO_LIST(seq) BOOST_PP_SEQ_TO_LIST_I(BOOST_PP_SEQ_BINARY_TRANSFORM(seq))
+# endif
# define BOOST_PP_SEQ_TO_LIST_I(bseq) BOOST_PP_SEQ_TO_LIST_A bseq BOOST_PP_NIL BOOST_PP_SEQ_TO_LIST_B bseq
# define BOOST_PP_SEQ_TO_LIST_A(m, e) m(BOOST_PP_LPAREN() e BOOST_PP_COMMA() BOOST_PP_SEQ_TO_LIST_A_ID)
# define BOOST_PP_SEQ_TO_LIST_A_ID() BOOST_PP_SEQ_TO_LIST_A
diff --git a/boost/process.hpp b/boost/process.hpp
new file mode 100644
index 0000000000..e0ad694358
--- /dev/null
+++ b/boost/process.hpp
@@ -0,0 +1,41 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2012 Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_HPP
+#define BOOST_PROCESS_HPP
+
+/**
+ * \file boost/process.hpp
+ *
+ * Convenience header which includes all public and platform-independent
+ * boost.process header files.
+ */
+
+#include <boost/process/args.hpp>
+#include <boost/process/async.hpp>
+#include <boost/process/async_system.hpp>
+#include <boost/process/group.hpp>
+#include <boost/process/child.hpp>
+#include <boost/process/cmd.hpp>
+#include <boost/process/env.hpp>
+#include <boost/process/environment.hpp>
+#include <boost/process/error.hpp>
+#include <boost/process/exe.hpp>
+#include <boost/process/group.hpp>
+#include <boost/process/io.hpp>
+#include <boost/process/pipe.hpp>
+#include <boost/process/shell.hpp>
+#include <boost/process/search_path.hpp>
+#include <boost/process/spawn.hpp>
+#include <boost/process/system.hpp>
+#include <boost/process/start_dir.hpp>
+
+#endif
diff --git a/boost/process/args.hpp b/boost/process/args.hpp
new file mode 100644
index 0000000000..af677cfd82
--- /dev/null
+++ b/boost/process/args.hpp
@@ -0,0 +1,279 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_ARGS_HPP
+#define BOOST_PROCESS_ARGS_HPP
+
+/** \file boost/process/args.hpp
+ *
+ * This header provides the \xmlonly <globalname alt="boost::process::args">args</globalname>\endxmlonly property. It also provides the
+ * alternative name \xmlonly <globalname alt="boost::process::argv">argv</globalname>\endxmlonly .
+ *
+ *
+\xmlonly
+<programlisting>
+namespace boost {
+ namespace process {
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::args">args</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::argv">argv</globalname>;
+ }
+}
+</programlisting>
+\endxmlonly
+ */
+
+
+#include <boost/process/detail/basic_cmd.hpp>
+#include <iterator>
+
+namespace boost { namespace process { namespace detail {
+
+struct args_
+{
+ template<typename T>
+ using remove_reference_t = typename std::remove_reference<T>::type;
+ template<typename T>
+ using value_type = typename remove_reference_t<T>::value_type;
+
+ template<typename T>
+ using vvalue_type = value_type<value_type<T>>;
+
+ template <class Range>
+ arg_setter_<vvalue_type<Range>, true> operator()(Range &&range) const
+ {
+ return arg_setter_<vvalue_type<Range>, true>(std::forward<Range>(range));
+ }
+ template <class Range>
+ arg_setter_<vvalue_type<Range>, true> operator+=(Range &&range) const
+ {
+ return arg_setter_<vvalue_type<Range>, true>(std::forward<Range>(range));
+ }
+ template <class Range>
+ arg_setter_<vvalue_type<Range>, false> operator= (Range &&range) const
+ {
+ return arg_setter_<vvalue_type<Range>, false>(std::forward<Range>(range));
+ }
+ template<typename Char>
+ arg_setter_<Char, true> operator()(std::basic_string<Char> && str) const
+ {
+ return arg_setter_<Char, true> (str);
+ }
+ template<typename Char>
+ arg_setter_<Char, true> operator+=(std::basic_string<Char> && str) const
+ {
+ return arg_setter_<Char, true> (str);
+ }
+ template<typename Char>
+ arg_setter_<Char, false> operator= (std::basic_string<Char> && str) const
+ {
+ return arg_setter_<Char, false>(str);
+ }
+ template<typename Char>
+ arg_setter_<Char, true> operator()(const std::basic_string<Char> & str) const
+ {
+ return arg_setter_<Char, true> (str);
+ }
+ template<typename Char>
+ arg_setter_<Char, true> operator+=(const std::basic_string<Char> & str) const
+ {
+ return arg_setter_<Char, true> (str);
+ }
+ template<typename Char>
+ arg_setter_<Char, false> operator= (const std::basic_string<Char> & str) const
+ {
+ return arg_setter_<Char, false>(str);
+ }
+ template<typename Char>
+ arg_setter_<Char, true> operator()(std::basic_string<Char> & str) const
+ {
+ return arg_setter_<Char, true> (str);
+ }
+ template<typename Char>
+ arg_setter_<Char, true> operator+=(std::basic_string<Char> & str) const
+ {
+ return arg_setter_<Char, true> (str);
+ }
+ template<typename Char>
+ arg_setter_<Char, false> operator= (std::basic_string<Char> & str) const
+ {
+ return arg_setter_<Char, false>(str);
+ }
+ template<typename Char>
+ arg_setter_<Char, true> operator()(const Char* str) const
+ {
+ return arg_setter_<Char, true> (str);
+ }
+ template<typename Char>
+ arg_setter_<Char, true> operator+=(const Char* str) const
+ {
+ return arg_setter_<Char, true> (str);
+ }
+ template<typename Char>
+ arg_setter_<Char, false> operator= (const Char* str) const
+ {
+ return arg_setter_<Char, false>(str);
+ }
+// template<typename Char, std::size_t Size>
+// arg_setter_<Char, true> operator()(const Char (&str) [Size]) const
+// {
+// return arg_setter_<Char, true> (str);
+// }
+// template<typename Char, std::size_t Size>
+// arg_setter_<Char, true> operator+=(const Char (&str) [Size]) const
+// {
+// return arg_setter_<Char, true> (str);
+// }
+// template<typename Char, std::size_t Size>
+// arg_setter_<Char, false> operator= (const Char (&str) [Size]) const
+// {
+// return arg_setter_<Char, false>(str);
+// }
+
+ arg_setter_<char, true> operator()(std::initializer_list<const char*> &&range) const
+ {
+ return arg_setter_<char>(range.begin(), range.end());
+ }
+ arg_setter_<char, true> operator+=(std::initializer_list<const char*> &&range) const
+ {
+ return arg_setter_<char, true>(range.begin(), range.end());
+ }
+ arg_setter_<char, false> operator= (std::initializer_list<const char*> &&range) const
+ {
+ return arg_setter_<char, true>(range.begin(), range.end());
+ }
+ arg_setter_<char, true> operator()(std::initializer_list<std::string> &&range) const
+ {
+ return arg_setter_<char>(range.begin(), range.end());
+ }
+ arg_setter_<char, true> operator+=(std::initializer_list<std::string> &&range) const
+ {
+ return arg_setter_<char, true>(range.begin(), range.end());
+ }
+ arg_setter_<char, false> operator= (std::initializer_list<std::string> &&range) const
+ {
+ return arg_setter_<char, true>(range.begin(), range.end());
+ }
+
+ arg_setter_<wchar_t, true> operator()(std::initializer_list<const wchar_t*> &&range) const
+ {
+ return arg_setter_<wchar_t>(range.begin(), range.end());
+ }
+ arg_setter_<wchar_t, true> operator+=(std::initializer_list<const wchar_t*> &&range) const
+ {
+ return arg_setter_<wchar_t, true>(range.begin(), range.end());
+ }
+ arg_setter_<wchar_t, false> operator= (std::initializer_list<const wchar_t*> &&range) const
+ {
+ return arg_setter_<wchar_t, true>(range.begin(), range.end());
+ }
+ arg_setter_<wchar_t, true> operator()(std::initializer_list<std::wstring> &&range) const
+ {
+ return arg_setter_<wchar_t>(range.begin(), range.end());
+ }
+ arg_setter_<wchar_t, true> operator+=(std::initializer_list<std::wstring> &&range) const
+ {
+ return arg_setter_<wchar_t, true>(range.begin(), range.end());
+ }
+ arg_setter_<wchar_t, false> operator= (std::initializer_list<std::wstring> &&range) const
+ {
+ return arg_setter_<wchar_t, true>(range.begin(), range.end());
+ }
+};
+
+
+}
+/**
+
+The `args` property allows to explicitly set arguments for the execution. The
+name of the executable will always be the first element in the arg-vector.
+
+\section args_details Details
+
+\subsection args_operations Operations
+
+\subsubsection args_set_var Setting values
+
+To set a the argument vector the following syntax can be used.
+
+\code{.cpp}
+args = value;
+args(value);
+\endcode
+
+`std::initializer_list` is among the allowed types, so the following syntax is also possible.
+
+\code{.cpp}
+args = {value1, value2};
+args({value1, value2});
+\endcode
+
+Below the possible types for `value` are listed, with `char_type` being either `char` or `wchar_t`.
+
+\paragraph args_set_var_value value
+
+ - `std::basic_string<char_type>`
+ - `const char_type * `
+ - `std::initializer_list<const char_type *>`
+ - `std::vector<std::basic_string<char_type>>`
+
+Additionally any range of `std::basic_string<char_type>` can be passed.
+
+\subsubsection args_append_var Appending values
+
+To append a the argument vector the following syntax can be used.
+
+\code{.cpp}
+args += value;
+\endcode
+
+`std::initializer_list` is among the allowed types, so the following syntax is also possible.
+
+\code{.cpp}
+args += {value1, value2};
+\endcode
+
+Below the possible types for `value` are listed, with `char_type` being either `char` or `wchar_t`.
+
+\paragraph args_append_var_value value
+
+ - `std::basic_string<char_type>`
+ - `const char_type * `
+ - `std::initializer_list<const char_type *>`
+ - `std::vector<std::basic_string<char_type>>`
+
+Additionally any range of `std::basic_string<char_type>` can be passed.
+
+
+\subsection args_example Example
+
+The overload form is used when more than one string is passed, from the second one forward.
+I.e. the following expressions have the same results:
+
+\code{.cpp}
+spawn("gcc", "--version");
+spawn("gcc", args ="--version");
+spawn("gcc", args+="--version");
+spawn("gcc", args ={"--version"});
+spawn("gcc", args+={"--version"});
+\endcode
+
+\note A string will be parsed and set in quotes if it has none and contains spaces.
+
+
+ */
+constexpr boost::process::detail::args_ args{};
+
+///Alias for \xmlonly <globalname alt="boost::process::args">args</globalname> \endxmlonly .
+constexpr boost::process::detail::args_ argv{};
+
+
+}}
+
+#endif
diff --git a/boost/process/async.hpp b/boost/process/async.hpp
new file mode 100644
index 0000000000..9698aab931
--- /dev/null
+++ b/boost/process/async.hpp
@@ -0,0 +1,130 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the 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 boost/process/async.hpp
+
+The header which provides the basic asynchrounous features.
+It provides the on_exit property, which allows callbacks when the process exits.
+It also implements the necessary traits for passing an boost::asio::io_service,
+which is needed for asynchronous communication.
+
+It also pulls the [boost::asio::buffer](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/buffer.html)
+into the boost::process namespace for convenience.
+
+\xmlonly
+<programlisting>
+namespace boost {
+ namespace process {
+ <emphasis>unspecified</emphasis> <ulink url="http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/buffer.html">buffer</ulink>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::on_exit">on_exit</globalname>;
+ }
+}
+</programlisting>
+
+\endxmlonly
+ */
+
+#ifndef BOOST_PROCESS_ASYNC_HPP_
+#define BOOST_PROCESS_ASYNC_HPP_
+
+#include <boost/process/detail/traits.hpp>
+#include <boost/process/detail/on_exit.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/streambuf.hpp>
+#include <boost/asio/buffer.hpp>
+#include <type_traits>
+#include <boost/fusion/iterator/deref.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/io_service_ref.hpp>
+#include <boost/process/detail/posix/async_in.hpp>
+#include <boost/process/detail/posix/async_out.hpp>
+#include <boost/process/detail/posix/on_exit.hpp>
+
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/io_service_ref.hpp>
+#include <boost/process/detail/windows/async_in.hpp>
+#include <boost/process/detail/windows/async_out.hpp>
+#include <boost/process/detail/windows/on_exit.hpp>
+#endif
+
+namespace boost { namespace process { namespace detail {
+
+struct async_tag;
+
+template<typename T>
+struct is_io_service : std::false_type {};
+template<>
+struct is_io_service<api::io_service_ref> : std::true_type {};
+
+template<typename Tuple>
+inline asio::io_service& get_io_service(const Tuple & tup)
+{
+ auto& ref = *boost::fusion::find_if<is_io_service<boost::mpl::_>>(tup);
+ return ref.get();
+}
+
+struct async_builder
+{
+ boost::asio::io_service * ios;
+
+ void operator()(boost::asio::io_service & ios_) {this->ios = &ios_;};
+
+ typedef api::io_service_ref result_type;
+ api::io_service_ref get_initializer() {return api::io_service_ref (*ios);};
+};
+
+
+template<>
+struct initializer_builder<async_tag>
+{
+ typedef async_builder type;
+};
+
+}
+
+using ::boost::asio::buffer;
+
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+/** When an io_service is passed, the on_exit property can be used, to be notified
+ when the child process exits.
+
+
+The following syntax is valid
+
+\code{.cpp}
+on_exit=function;
+on_exit(function);
+\endcode
+
+with `function` being a callable object with the signature `(int, const std::error_code&)` or an
+`std::future<int>`.
+
+\par Example
+
+\code{.cpp}
+io_service ios;
+
+child c("ls", on_exit=[](int exit, const std::error_code& ec_in){});
+
+std::future<int> exit_code;
+chlid c2("ls", on_exit=exit_code);
+
+\endcode
+
+\note The handler is not invoked when the launch fails.
+\warning When used \ref ignore_error it might gte invoked on error.
+
+ */
+constexpr static ::boost::process::detail::on_exit_ on_exit{};
+#endif
+
+}}
+
+
+
+#endif /* INCLUDE_BOOST_PROCESS_DETAIL_ASYNC_HPP_ */
diff --git a/boost/process/async_pipe.hpp b/boost/process/async_pipe.hpp
new file mode 100644
index 0000000000..97af165859
--- /dev/null
+++ b/boost/process/async_pipe.hpp
@@ -0,0 +1,215 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_ASYNC_PIPE_HPP
+#define BOOST_PROCESS_ASYNC_PIPE_HPP
+
+#include <boost/config.hpp>
+#include <boost/process/detail/config.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/async_pipe.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/async_pipe.hpp>
+#endif
+
+namespace boost { namespace process {
+
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+
+
+/** Class implementing and asnychronous I/O-Object for use with boost.asio.
+ * It is based on the corresponding I/O Object, that is either boost::asio::windows::stream_handle or
+ * boost::asio::posix::stream_descriptor.
+ *
+ * It can be used directly with boost::asio::async_read or async_write.
+ *
+ * \note The object is copyable, but that does invoke a handle duplicate.
+ */
+class async_pipe
+{
+public:
+ /** Typedef for the native handle representation.
+ * \note This is the handle on the system, not the boost.asio class.
+ *
+ */
+ typedef platform_specific native_handle_type;
+ /** Typedef for the handle representation of boost.asio.
+ *
+ */
+ typedef platform_specific handle_type;
+
+ /** Construct a new async_pipe, does automatically open the pipe.
+ * Initializes source and sink with the same io_service.
+ * @note Windows creates a named pipe here, where the name is automatically generated.
+ */
+ inline async_pipe(boost::asio::io_service & ios);
+
+ /** Construct a new async_pipe, does automatically open the pipe.
+ * @note Windows creates a named pipe here, where the name is automatically generated.
+ */
+ inline async_pipe(boost::asio::io_service & ios_source,
+ boost::asio::io_service & ios_sink);
+
+ /** Construct a new async_pipe, does automatically open.
+ * Initializes source and sink with the same io_service.
+ *
+ * @note Windows restricts possible names.
+ */
+ inline async_pipe(boost::asio::io_service & ios, const std::string & name);
+
+
+ /** Construct a new async_pipe, does automatically open.
+ *
+ * @note Windows restricts possible names.
+ */
+ inline async_pipe(boost::asio::io_service & ios_source,
+ boost::asio::io_service & ios_sink, const std::string & name);
+
+ /** Copy-Constructor of the async pipe.
+ * @note Windows requires a named pipe for this, if a the wrong type is used an exception is thrown.
+ *
+ */
+ async_pipe(const async_pipe& lhs);
+
+ /** Move-Constructor of the async pipe.
+ */
+ async_pipe(async_pipe&& lhs);
+
+ /** Construct the async-pipe from a pipe.
+ * @note Windows requires a named pipe for this, if a the wrong type is used an exception is thrown.
+ *
+ */
+ template<class CharT, class Traits = std::char_traits<CharT>>
+ explicit async_pipe(boost::asio::io_service & ios, const basic_pipe<CharT, Traits> & p);
+
+ /** Construct the async-pipe from a pipe, with two different io_service objects.
+ * @note Windows requires a named pipe for this, if a the wrong type is used an exception is thrown.
+ *
+ */
+ template<class CharT, class Traits = std::char_traits<CharT>>
+ explicit async_pipe(boost::asio::io_service & ios_source,
+ boost::asio::io_service & ios_sink,
+ const basic_pipe<CharT, Traits> & p);
+
+
+ /** Assign a basic_pipe.
+ * @note Windows requires a named pipe for this, if a the wrong type is used an exception is thrown.
+ *
+ */
+ template<class CharT, class Traits = std::char_traits<CharT>>
+ inline async_pipe& operator=(const basic_pipe<CharT, Traits>& p);
+
+ /** Copy Assign a pipe.
+ * @note Duplicates the handles.
+ */
+ async_pipe& operator=(const async_pipe& lhs);
+ /** Move assign a pipe */
+ async_pipe& operator=(async_pipe&& lhs);
+
+ /** Destructor. Closes the pipe handles. */
+ ~async_pipe();
+
+ /** Explicit cast to basic_pipe. */
+ template<class CharT, class Traits = std::char_traits<CharT>>
+ inline explicit operator basic_pipe<CharT, Traits>() const;
+
+ /** Cancel the current asynchronous operations. */
+ void cancel();
+ /** Close the pipe handles. */
+ void close();
+ /** Close the pipe handles. While passing an error_code
+ *
+ */
+ void close(std::error_code & ec);
+
+ /** Check if the pipes are open. */
+ bool is_open() const;
+
+ /** Async close, i.e. close after current operation is completed.
+ *
+ * \note There is no guarantee that this will indeed read the entire pipe-buffer
+ */
+ void async_close();
+
+ /** Read some data from the handle.
+
+ * See the boost.asio documentation for more details.
+ */
+ template<typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence & buffers);
+
+ /** Write some data to the handle.
+
+ * See the boost.asio documentation for more details.
+ */
+ template<typename MutableBufferSequence>
+ std::size_t write_some(const MutableBufferSequence & buffers);
+
+ /** Get the native handle of the source. */
+ native_handle native_source() const {return const_cast<boost::asio::windows::stream_handle&>(_source).native();}
+ /** Get the native handle of the sink. */
+ native_handle native_sink () const {return const_cast<boost::asio::windows::stream_handle&>(_sink ).native();}
+
+ /** Start an asynchronous read.
+ *
+ * See the [boost.asio documentation](http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncReadStream.html) for more details.
+ */
+ template<typename MutableBufferSequence,
+ typename ReadHandler>
+ detail::dummy async_read_some(
+ const MutableBufferSequence & buffers,
+ ReadHandler &&handler);
+
+ /** Start an asynchronous write.
+
+ * See the [boost.asio documentation](http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncWriteStream.html) for more details.
+ */
+ template<typename ConstBufferSequence,
+ typename WriteHandler>
+ detail::dummy async_write_some(
+ const ConstBufferSequence & buffers,
+ WriteHandler && handler);
+
+ ///Get the asio handle of the pipe sink.
+ const handle_type & sink () const &;
+ ///Get the asio handle of the pipe source.
+ const handle_type & source() const &;
+
+ ///Get the asio handle of the pipe sink. Qualified as rvalue
+ handle_type && sink () &&;
+ ///Get the asio handle of the pipe source. Qualified as rvalue
+ handle_type && source() &&;
+
+ /// Move the source out of this class and change the io_service. Qualified as rvalue. \attention Will always move.
+ handle_type source(::boost::asio::io_service& ios) &&;
+ /// Move the sink out of this class and change the io_service. Qualified as rvalue. \attention Will always move
+ handle_type sink (::boost::asio::io_service& ios) &&;
+
+ /// Copy the source out of this class and change the io_service. \attention Will always copy.
+ handle_type source(::boost::asio::io_service& ios) const &;
+ /// Copy the sink out of this class and change the io_service. \attention Will always copy
+ handle_type sink (::boost::asio::io_service& ios) const &;
+
+
+
+};
+
+#else
+using ::boost::process::detail::api::async_pipe;
+#endif
+
+
+}}
+
+
+
+#endif
diff --git a/boost/process/async_system.hpp b/boost/process/async_system.hpp
new file mode 100644
index 0000000000..f92b417d2e
--- /dev/null
+++ b/boost/process/async_system.hpp
@@ -0,0 +1,142 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the 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 boost/process/async_system.hpp
+ *
+ * Defines the asynchrounous version of the system function.
+ */
+
+#ifndef BOOST_PROCESS_ASYNC_SYSTEM_HPP
+#define BOOST_PROCESS_ASYNC_SYSTEM_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/async.hpp>
+#include <boost/process/child.hpp>
+#include <boost/process/detail/async_handler.hpp>
+#include <boost/process/detail/execute_impl.hpp>
+#include <type_traits>
+#include <memory>
+#include <boost/asio/async_result.hpp>
+#include <boost/system/error_code.hpp>
+#include <tuple>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/posix.hpp>
+#endif
+
+namespace boost {
+namespace process {
+namespace detail
+{
+
+template<typename ExitHandler>
+struct async_system_handler : ::boost::process::detail::api::async_handler
+{
+ boost::asio::io_service & ios;
+ boost::asio::detail::async_result_init<
+ ExitHandler, void(boost::system::error_code, int)> init;
+
+#if defined(BOOST_POSIX_API)
+ bool errored = false;
+#endif
+
+ template<typename ExitHandler_>
+ async_system_handler(
+ boost::asio::io_service & ios,
+ ExitHandler_ && exit_handler) : ios(ios), init(std::forward<ExitHandler_>(exit_handler))
+ {
+
+ }
+
+
+ template<typename Exec>
+ void on_error(Exec&, const std::error_code & ec)
+ {
+#if defined(BOOST_POSIX_API)
+ errored = true;
+#endif
+ auto & h = init.handler;
+ ios.post(
+ [h, ec]() mutable
+ {
+ h(boost::system::error_code(ec.value(), boost::system::system_category()), -1);
+ });
+ }
+
+ BOOST_ASIO_INITFN_RESULT_TYPE(ExitHandler, void (boost::system::error_code, int))
+ get_result()
+ {
+ return init.result.get();
+ }
+
+ template<typename Executor>
+ std::function<void(int, const std::error_code&)> on_exit_handler(Executor&)
+ {
+#if defined(BOOST_POSIX_API)
+ if (errored)
+ return [](int exit_code, const std::error_code & ec){};
+#endif
+ auto & h = init.handler;
+ return [h](int exit_code, const std::error_code & ec) mutable
+ {
+ h(boost::system::error_code(ec.value(), boost::system::system_category()), exit_code);
+ };
+ }
+};
+
+
+template<typename ExitHandler>
+struct is_error_handler<async_system_handler<ExitHandler>> : std::true_type {};
+
+}
+
+/** This function provides an asynchronous interface to process launching.
+
+It uses the same properties and parameters as the other launching function,
+but is similar to the asynchronous functions in [boost.asio](http://www.boost.org/doc/libs/release/doc/html/boost_asio.html)
+
+It uses [asio::async_result](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/async_result.html) to determine
+the return value (from the second parameter, `exit_handler`).
+
+\param ios A reference to an [io_service](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference.html)
+\param exit_handler The exit-handler for the signature `void(boost::system::error_code, int)`
+
+\note This function does not allow custom error handling, since those are done through the `exit_handler`.
+
+*/
+#if defined(BOOST_PROCESS_DOXYGEN)
+template<typename ExitHandler, typename ...Args>
+inline boost::process::detail::dummy
+ async_system(boost::asio::io_service & ios, ExitHandler && exit_handler, Args && ...args);
+#endif
+
+template<typename ExitHandler, typename ...Args>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(ExitHandler, void (boost::system::error_code, int))
+ async_system(boost::asio::io_service & ios, ExitHandler && exit_handler, Args && ...args)
+{
+ detail::async_system_handler<ExitHandler> async_h{ios, std::forward<ExitHandler>(exit_handler)};
+
+ typedef typename ::boost::process::detail::has_error_handler<boost::fusion::tuple<Args...>>::type
+ has_err_handling;
+
+ static_assert(!has_err_handling::value, "async_system cannot have custom error handling");
+
+
+ child(ios, std::forward<Args>(args)..., async_h ).detach();
+
+ return async_h.get_result();
+}
+
+
+
+}}
+#endif
+
diff --git a/boost/process/child.hpp b/boost/process/child.hpp
new file mode 100644
index 0000000000..980cecdae7
--- /dev/null
+++ b/boost/process/child.hpp
@@ -0,0 +1,147 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the 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 boost/process/child.hpp
+ *
+ * Defines a child process class.
+ */
+
+#ifndef BOOST_PROCESS_CHILD_HPP
+#define BOOST_PROCESS_CHILD_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/child_decl.hpp>
+#include <boost/process/detail/execute_impl.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/posix.hpp>
+#endif
+
+namespace boost {
+
+///The main namespace of boost.process.
+namespace process {
+
+template<typename ...Args>
+child::child(Args&&...args)
+ : child(::boost::process::detail::execute_impl(std::forward<Args>(args)...)) {}
+
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+/** The main class to hold a child process. It is simliar to [std::thread](http://en.cppreference.com/w/cpp/thread/thread),
+ * in that it has a join and detach function.
+ *
+ * @attention The destructor will call terminate on the process if not joined or detached without any warning.
+ *
+ */
+
+class child
+{
+ /** Type definition for the native process handle. */
+ typedef platform_specific native_handle_t;
+
+ /** Construct the child from a pid.
+ *
+ * @attention There is no guarantee that this will work. The process need the right access rights, which are very platform specific.
+ */
+ explicit child(pid_t & pid) : _child_handle(pid) {};
+
+ /** Move-Constructor.*/
+ child(child && lhs);
+
+ /** Construct a child from a property list and launch it
+ * The standard version is to create a subprocess, which will spawn the process.
+ */
+ template<typename ...Args>
+ explicit child(Args&&...args);
+
+ /** Construct an empty child. */
+ child() = default;
+
+ /** Move assign. */
+ child& operator=(child && lhs);
+
+ /** Detach the child, i.e. let it run after this handle dies. */
+ void detach();
+ /** Join the child. This just calls wait, but that way the naming is similar to std::thread */
+ void join();
+ /** Check if the child is joinable. */
+ bool joinable();
+
+ /** Destructor.
+ * @attention Will call terminate (without warning) when the child was neither joined nor detached.
+ */
+ ~child();
+
+ /** Get the native handle for the child process. */
+ native_handle_t native_handle() const;
+
+ /** Get the exit_code. The return value is without any meaning if the child wasn't waited for or if it was terminated. */
+ int exit_code() const;
+ /** Get the Process Identifier. */
+ pid_t id() const;
+
+ /** Check if the child process is running. */
+ bool running();
+ /** \overload void running() */
+ bool running(std::error_code & ec) noexcept;
+
+ /** Wait for the child process to exit. */
+ void wait();
+ /** \overload void wait() */
+ void wait(std::error_code & ec) noexcept;
+
+ /** Wait for the child process to exit for a period of time.
+ * \return True if child exited while waiting.
+ */
+ template< class Rep, class Period >
+ bool wait_for (const std::chrono::duration<Rep, Period>& rel_time);
+ /** \overload bool wait_for(const std::chrono::duration<Rep, Period>& rel_time) */
+ bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept;
+
+ /** Wait for the child process to exit until a point in time.
+ * \return True if child exited while waiting.*/
+ template< class Clock, class Duration >
+ bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time );
+ /** \overload bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time )*/
+ bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, std::error_code & ec) noexcept;
+
+ /** Check if this handle holds a child process.
+ * @note That does not mean, that the process is still running. It only means, that the handle does or did exist.
+ */
+ bool valid() const;
+ /** Same as valid, for convenience. */
+ explicit operator bool() const;
+
+ /** Check if the the chlid process is in any process group. */
+ bool in_group() const;
+
+ /** \overload bool in_group() const */
+ bool in_group(std::error_code & ec) const noexcept;
+
+ /** Terminate the child process.
+ *
+ * This function will cause the child process to unconditionally and immediately exit.
+ * It is implement with [SIGKILL](http://pubs.opengroup.org/onlinepubs/009695399/functions/kill.html) on posix
+ * and [TerminateProcess](https://technet.microsoft.com/en-us/library/ms686714.aspx) on windows.
+ *
+ */
+ void terminate();
+
+ /** \overload void terminate() */
+ void terminate(std::error_code & ec) noexcept;
+};
+
+#endif
+
+}}
+#endif
+
diff --git a/boost/process/cmd.hpp b/boost/process/cmd.hpp
new file mode 100644
index 0000000000..5985c81430
--- /dev/null
+++ b/boost/process/cmd.hpp
@@ -0,0 +1,122 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_CMD_LINE_HPP
+#define BOOST_PROCESS_DETAIL_CMD_LINE_HPP
+
+#include <boost/detail/winapi/config.hpp>
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/traits/cmd_or_exe.hpp>
+#include <boost/process/detail/traits/wchar_t.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/cmd.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/cmd.hpp>
+#endif
+
+/** \file boost/process/cmd.hpp
+ *
+ * This header provides the \xmlonly <globalname alt="boost::process::cmd">cmd</globalname>\endxmlonly property.
+ *
+\xmlonly
+<programlisting>
+namespace boost {
+ namespace process {
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::cmd">cmd</globalname>;
+ }
+}
+</programlisting>
+\endxmlonly
+*/
+
+namespace boost { namespace process { namespace detail {
+
+
+struct cmd_
+{
+ constexpr cmd_() {}
+
+ template<typename Char>
+ inline api::cmd_setter_<Char> operator()(const Char *s) const
+ {
+ return api::cmd_setter_<Char>(s);
+ }
+ template<typename Char>
+ inline api::cmd_setter_<Char> operator= (const Char *s) const
+ {
+ return api::cmd_setter_<Char>(s);
+ }
+
+ template<typename Char>
+ inline api::cmd_setter_<Char> operator()(const std::basic_string<Char> &s) const
+ {
+ return api::cmd_setter_<Char>(s);
+ }
+ template<typename Char>
+ inline api::cmd_setter_<Char> operator= (const std::basic_string<Char> &s) const
+ {
+ return api::cmd_setter_<Char>(s);
+ }
+};
+
+template<> struct is_wchar_t<api::cmd_setter_<wchar_t>> : std::true_type {};
+
+
+
+template<>
+struct char_converter<char, api::cmd_setter_<wchar_t>>
+{
+ static api::cmd_setter_<char> conv(const api::cmd_setter_<wchar_t> & in)
+ {
+ return { ::boost::process::detail::convert(in.str()) };
+ }
+};
+
+template<>
+struct char_converter<wchar_t, api::cmd_setter_<char>>
+{
+ static api::cmd_setter_<wchar_t> conv(const api::cmd_setter_<char> & in)
+ {
+ return { ::boost::process::detail::convert(in.str()) };
+ }
+};
+
+
+
+
+
+
+}
+
+
+/** The cmd property allows to explicitly set commands for the execution.
+
+The overload form applies when only one string is passed to a launching function.
+The string will be internally parsed and split at spaces.
+
+The following expressions are valid, with `value` being either a C-String or
+a `std::basic_string` with `char` or `wchar_t`.
+
+\code{.cpp}
+cmd="value";
+cmd(value);
+\endcode
+
+The property can only be used for assignments.
+
+
+ */
+constexpr static ::boost::process::detail::cmd_ cmd;
+
+}}
+
+#endif
diff --git a/boost/process/detail/async_handler.hpp b/boost/process/detail/async_handler.hpp
new file mode 100644
index 0000000000..832a42014e
--- /dev/null
+++ b/boost/process/detail/async_handler.hpp
@@ -0,0 +1,117 @@
+/*
+ * async_handler.hpp
+ *
+ * Created on: 12.06.2016
+ * Author: Klemens
+ */
+
+#ifndef BOOST_PROCESS_DETAIL_ASYNC_HANDLER_HPP_
+#define BOOST_PROCESS_DETAIL_ASYNC_HANDLER_HPP_
+
+#include <type_traits>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/posix.hpp>
+#include <boost/process/detail/posix/async_handler.hpp>
+#include <boost/process/detail/posix/asio_fwd.hpp>
+#else
+#include <boost/process/detail/windows/async_handler.hpp>
+#include <boost/process/detail/windows/asio_fwd.hpp>
+#endif
+
+namespace boost {
+
+namespace process {
+
+namespace detail {
+
+#if defined(BOOST_POSIX_API)
+using ::boost::process::detail::posix::is_async_handler;
+using ::boost::process::detail::posix::does_require_io_service;
+#else
+using ::boost::process::detail::windows::is_async_handler;
+using ::boost::process::detail::windows::does_require_io_service;
+#endif
+
+template<typename ...Args>
+struct has_io_service;
+
+template<typename T, typename ...Args>
+struct has_io_service<T, Args...>
+{
+ typedef typename has_io_service<Args...>::type next;
+ typedef typename std::is_same<
+ typename std::remove_reference<T>::type,
+ boost::asio::io_service>::type is_ios;
+ typedef typename std::conditional<is_ios::value,
+ std::true_type,
+ next>::type type;
+};
+
+template<typename T>
+struct has_io_service<T>
+{
+ typedef typename std::is_same<
+ typename std::remove_reference<T>::type,
+ boost::asio::io_service>::type type;
+};
+
+template<typename ...Args>
+using has_io_service_t = typename has_io_service<Args...>::type;
+
+template<typename ...Args>
+struct has_async_handler;
+
+template<typename T, typename ...Args>
+struct has_async_handler<T, Args...>
+{
+ typedef typename has_async_handler<Args...>::type next;
+ typedef typename is_async_handler<T>::type is_ios;
+ typedef typename std::conditional<is_ios::value,
+ std::true_type,
+ next>::type type;
+};
+
+template<typename T>
+struct has_async_handler<T>
+{
+ typedef typename is_async_handler<T>::type type;
+};
+
+template<typename ...Args>
+struct needs_io_service;
+
+template<typename T, typename ...Args>
+struct needs_io_service<T, Args...>
+{
+ typedef typename needs_io_service<Args...>::type next;
+ typedef typename does_require_io_service<T>::type is_ios;
+ typedef typename std::conditional<is_ios::value,
+ std::true_type,
+ next>::type type;
+};
+
+template<typename T>
+struct needs_io_service<T>
+{
+ typedef typename does_require_io_service<T>::type type;
+};
+
+template<typename ...Args>
+boost::asio::io_service &get_io_service_var(boost::asio::io_service & f, Args&...)
+{
+ return f;
+}
+
+template<typename First, typename ...Args>
+boost::asio::io_service &get_io_service_var(First&, Args&...args)
+{
+ return get_io_service_var(args...);
+}
+
+}
+}
+}
+
+
+#endif /* BOOST_PROCESS_DETAIL_ASYNC_HANDLER_HPP_ */
diff --git a/boost/process/detail/basic_cmd.hpp b/boost/process/detail/basic_cmd.hpp
new file mode 100644
index 0000000000..e387d9f0c5
--- /dev/null
+++ b/boost/process/detail/basic_cmd.hpp
@@ -0,0 +1,292 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_BASIC_CMD_HPP_
+#define BOOST_PROCESS_DETAIL_BASIC_CMD_HPP_
+
+#include <boost/process/detail/config.hpp>
+
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/traits/cmd_or_exe.hpp>
+#include <boost/process/detail/traits/wchar_t.hpp>
+
+#if defined( BOOST_WINDOWS_API )
+#include <boost/process/detail/windows/basic_cmd.hpp>
+#include <boost/process/detail/windows/cmd.hpp>
+#elif defined( BOOST_POSIX_API )
+#include <boost/process/detail/posix/basic_cmd.hpp>
+#include <boost/process/detail/posix/cmd.hpp>
+#endif
+
+#include <boost/process/shell.hpp>
+
+#include <iterator>
+
+
+namespace boost { namespace process { namespace detail {
+
+template<typename Char>
+struct exe_setter_
+{
+ typedef Char value_type;
+ typedef std::basic_string<Char> string_type;
+
+ string_type exe_;
+ exe_setter_(string_type && str) : exe_(std::move(str)) {}
+ exe_setter_(const string_type & str) : exe_(str) {}
+};
+
+template<> struct is_wchar_t<exe_setter_<wchar_t>> : std::true_type {};
+
+
+template<>
+struct char_converter<char, exe_setter_<wchar_t>>
+{
+ static exe_setter_<char> conv(const exe_setter_<wchar_t> & in)
+ {
+ return {::boost::process::detail::convert(in.exe_)};
+ }
+};
+
+template<>
+struct char_converter<wchar_t, exe_setter_<char>>
+{
+ static exe_setter_<wchar_t> conv(const exe_setter_<char> & in)
+ {
+ return {::boost::process::detail::convert(in.exe_)};
+ }
+};
+
+
+
+template <typename Char, bool Append >
+struct arg_setter_
+{
+ using value_type = Char;
+ using string_type = std::basic_string<value_type>;
+ std::vector<string_type> _args;
+
+ typedef typename std::vector<string_type>::iterator iterator;
+ typedef typename std::vector<string_type>::const_iterator const_iterator;
+
+ template<typename Iterator>
+ arg_setter_(Iterator && begin, Iterator && end) : _args(begin, end) {}
+
+ template<typename Range>
+ arg_setter_(Range && str) :
+ _args(std::begin(str),
+ std::end(str)) {}
+
+ iterator begin() {return _args.begin();}
+ iterator end() {return _args.end();}
+ const_iterator begin() const {return _args.begin();}
+ const_iterator end() const {return _args.end();}
+ arg_setter_(string_type & str) : _args{{str}} {}
+ arg_setter_(string_type && s) : _args({std::move(s)}) {}
+ arg_setter_(const string_type & s) : _args({s}) {}
+ arg_setter_(const value_type* s) : _args({std::move(s)}) {}
+
+ template<std::size_t Size>
+ arg_setter_(const value_type (&s) [Size]) : _args({s}) {}
+};
+
+template<> struct is_wchar_t<arg_setter_<wchar_t, true >> : std::true_type {};
+template<> struct is_wchar_t<arg_setter_<wchar_t, false>> : std::true_type {};
+
+template<>
+struct char_converter<char, arg_setter_<wchar_t, true>>
+{
+ static arg_setter_<char, true> conv(const arg_setter_<wchar_t, true> & in)
+ {
+ std::vector<std::string> vec(in._args.size());
+ std::transform(in._args.begin(), in._args.end(), vec.begin(),
+ [](const std::wstring & ws)
+ {
+ return ::boost::process::detail::convert(ws);
+ });
+ return {vec};
+ }
+};
+
+template<>
+struct char_converter<wchar_t, arg_setter_<char, true>>
+{
+ static arg_setter_<wchar_t, true> conv(const arg_setter_<char, true> & in)
+ {
+ std::vector<std::wstring> vec(in._args.size());
+ std::transform(in._args.begin(), in._args.end(), vec.begin(),
+ [](const std::string & ws)
+ {
+ return ::boost::process::detail::convert(ws);
+ });
+
+ return {vec};
+ }
+};
+
+template<>
+struct char_converter<char, arg_setter_<wchar_t, false>>
+{
+ static arg_setter_<char, false> conv(const arg_setter_<wchar_t, false> & in)
+ {
+ std::vector<std::string> vec(in._args.size());
+ std::transform(in._args.begin(), in._args.end(), vec.begin(),
+ [](const std::wstring & ws)
+ {
+ return ::boost::process::detail::convert(ws);
+ });
+ return {vec}; }
+};
+
+template<>
+struct char_converter<wchar_t, arg_setter_<char, false>>
+{
+ static arg_setter_<wchar_t, false> conv(const arg_setter_<char, false> & in)
+ {
+ std::vector<std::wstring> vec(in._args.size());
+ std::transform(in._args.begin(), in._args.end(), vec.begin(),
+ [](const std::string & ws)
+ {
+ return ::boost::process::detail::convert(ws);
+ });
+ return {vec};
+ }
+};
+
+using api::exe_cmd_init;
+
+template<typename Char>
+struct exe_builder
+{
+ //set by path, because that will not be interpreted as a cmd
+ bool not_cmd = false;
+ bool shell = false;
+ using string_type = std::basic_string<Char>;
+ string_type exe;
+ std::vector<string_type> args;
+
+ void operator()(const boost::filesystem::path & data)
+ {
+ not_cmd = true;
+ if (exe.empty())
+ exe = data.native();
+ else
+ args.push_back(data.native());
+ }
+
+ void operator()(const string_type & data)
+ {
+ if (exe.empty())
+ exe = data;
+ else
+ args.push_back(data);
+ }
+ void operator()(const Char* data)
+ {
+ if (exe.empty())
+ exe = data;
+ else
+ args.push_back(data);
+ }
+ void operator()(shell_) {shell = true;}
+ void operator()(std::vector<string_type> && data)
+ {
+ if (data.empty())
+ return;
+
+ auto itr = std::make_move_iterator(data.begin());
+ auto end = std::make_move_iterator(data.end());
+
+ if (exe.empty())
+ {
+ exe = *itr;
+ itr++;
+ }
+ args.insert(args.end(), itr, end);
+ }
+
+ void operator()(const std::vector<string_type> & data)
+ {
+ if (data.empty())
+ return;
+
+ auto itr = data.begin();
+ auto end = data.end();
+
+ if (exe.empty())
+ {
+ exe = *itr;
+ itr++;
+ }
+ args.insert(args.end(), itr, end);
+ }
+ void operator()(exe_setter_<Char> && data)
+ {
+ not_cmd = true;
+ exe = std::move(data.exe_);
+ }
+ void operator()(const exe_setter_<Char> & data)
+ {
+ not_cmd = true;
+ exe = data.exe_;
+ }
+ void operator()(arg_setter_<Char, false> && data)
+ {
+ args.assign(
+ std::make_move_iterator(data._args.begin()),
+ std::make_move_iterator(data._args.end()));
+ }
+ void operator()(arg_setter_<Char, true> && data)
+ {
+ args.insert(args.end(),
+ std::make_move_iterator(data._args.begin()),
+ std::make_move_iterator(data._args.end()));
+ }
+ void operator()(const arg_setter_<Char, false> & data)
+ {
+ args.assign(data._args.begin(), data._args.end());
+ }
+ void operator()(const arg_setter_<Char, true> & data)
+ {
+ args.insert(args.end(), data._args.begin(), data._args.end());
+ }
+
+ api::exe_cmd_init<Char> get_initializer()
+ {
+ if (not_cmd || !args.empty())
+ {
+ if (shell)
+ return api::exe_cmd_init<Char>::exe_args_shell(std::move(exe), std::move(args));
+ else
+ return api::exe_cmd_init<Char>::exe_args(std::move(exe), std::move(args));
+ }
+ else
+ if (shell)
+ return api::exe_cmd_init<Char>::cmd_shell(std::move(exe));
+ else
+ return api::exe_cmd_init<Char>::cmd(std::move(exe));
+
+ }
+ typedef api::exe_cmd_init<Char> result_type;
+};
+
+template<>
+struct initializer_builder<cmd_or_exe_tag<char>>
+{
+ typedef exe_builder<char> type;
+};
+
+template<>
+struct initializer_builder<cmd_or_exe_tag<wchar_t>>
+{
+ typedef exe_builder<wchar_t> type;
+};
+
+}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_EXE_BUILDER_HPP_ */
diff --git a/boost/process/detail/child_decl.hpp b/boost/process/detail/child_decl.hpp
new file mode 100644
index 0000000000..3483f7c4b8
--- /dev/null
+++ b/boost/process/detail/child_decl.hpp
@@ -0,0 +1,243 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the 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 boost/process/child.hpp
+ *
+ * Defines a child process class.
+ */
+
+#ifndef BOOST_PROCESS_CHILD_DECL_HPP
+#define BOOST_PROCESS_CHILD_DECL_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <chrono>
+#include <memory>
+
+#include <boost/none.hpp>
+#include <atomic>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/child_handle.hpp>
+#include <boost/process/detail/posix/terminate.hpp>
+#include <boost/process/detail/posix/wait_for_exit.hpp>
+#include <boost/process/detail/posix/is_running.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/child_handle.hpp>
+#include <boost/process/detail/windows/terminate.hpp>
+#include <boost/process/detail/windows/wait_for_exit.hpp>
+#include <boost/process/detail/windows/is_running.hpp>
+
+#endif
+namespace boost {
+
+namespace process {
+
+using ::boost::process::detail::api::pid_t;
+
+class child
+{
+ ::boost::process::detail::api::child_handle _child_handle;
+ std::shared_ptr<std::atomic<int>> _exit_status = std::make_shared<std::atomic<int>>(::boost::process::detail::api::still_active);
+ bool _attached = true;
+ bool _terminated = false;
+
+ bool _exited()
+ {
+ return _terminated || !::boost::process::detail::api::is_running(_exit_status->load());
+ };
+public:
+ typedef ::boost::process::detail::api::child_handle child_handle;
+ typedef child_handle::process_handle_t native_handle_t;
+ explicit child(child_handle &&ch, std::shared_ptr<std::atomic<int>> &ptr) : _child_handle(std::move(ch)), _exit_status(ptr) {}
+ explicit child(child_handle &&ch, const std::shared_ptr<std::atomic<int>> &ptr) : _child_handle(std::move(ch)), _exit_status(ptr) {}
+ explicit child(child_handle &&ch) : _child_handle(std::move(ch)) {}
+
+ explicit child(pid_t & pid) : _child_handle(pid), _attached(false) {};
+ child(const child&) = delete;
+ child(child && lhs) noexcept
+ : _child_handle(std::move(lhs._child_handle)),
+ _exit_status(std::move(lhs._exit_status)),
+ _attached (lhs._attached)
+ {
+ lhs._attached = false;
+ }
+
+ template<typename ...Args>
+ explicit child(Args&&...args);
+ child() {}
+ child& operator=(const child&) = delete;
+ child& operator=(child && lhs)
+ {
+ _child_handle= std::move(lhs._child_handle);
+ _exit_status = std::move(lhs._exit_status);
+ _attached = lhs._attached;
+ lhs._attached = false;
+ return *this;
+ };
+
+ void detach() {_attached = false; }
+ void join() {wait();}
+ bool joinable() { return _attached;}
+
+ ~child()
+ {
+ std::error_code ec;
+ if (_attached && !_exited() && running(ec))
+ terminate(ec);
+ }
+ native_handle_t native_handle() const { return _child_handle.process_handle(); }
+
+
+ int exit_code() const {return ::boost::process::detail::api::eval_exit_status(_exit_status->load());}
+ pid_t id() const {return _child_handle.id(); }
+
+ bool running()
+ {
+ if (valid() && !_exited())
+ {
+ int code;
+ auto res = boost::process::detail::api::is_running(_child_handle, code);
+ if (!res && !_exited())
+ _exit_status->store(code);
+
+ return res;
+ }
+ return false;
+ }
+
+ void terminate()
+ {
+ if (valid() && running())
+ boost::process::detail::api::terminate(_child_handle);
+
+ _terminated = true;
+ }
+
+ void wait()
+ {
+ if (!_exited() && valid())
+ {
+ int exit_code = 0;
+ boost::process::detail::api::wait(_child_handle, exit_code);
+ _exit_status->store(exit_code);
+ }
+ }
+
+ template< class Rep, class Period >
+ bool wait_for (const std::chrono::duration<Rep, Period>& rel_time)
+ {
+ if (!_exited())
+ {
+ int exit_code = 0;
+ auto b = boost::process::detail::api::wait_for(_child_handle, exit_code, rel_time);
+ if (!b)
+ return false;
+ _exit_status->store(exit_code);
+ }
+ return true;
+ }
+
+ template< class Clock, class Duration >
+ bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time )
+ {
+ if (!_exited())
+ {
+ int exit_code = 0;
+ auto b = boost::process::detail::api::wait_until(_child_handle, exit_code, timeout_time);
+ if (!b)
+ return false;
+ _exit_status->store(exit_code);
+ }
+ return true;
+ }
+
+ bool running(std::error_code & ec) noexcept
+ {
+ if (valid() && !_exited())
+ {
+ int code;
+ auto res = boost::process::detail::api::is_running(_child_handle, code, ec);
+ if (!res && !_exited())
+ _exit_status->store(code);
+
+ return res;
+ }
+ return false;
+ }
+
+ void terminate(std::error_code & ec) noexcept
+ {
+ if (valid() && running(ec))
+ boost::process::detail::api::terminate(_child_handle, ec);
+
+ _terminated = true;
+ }
+
+ void wait(std::error_code & ec) noexcept
+ {
+ if (!_exited() && valid())
+ {
+ int exit_code = 0;
+ boost::process::detail::api::wait(_child_handle, exit_code, ec);
+ _exit_status->store(exit_code);
+ }
+ }
+
+ template< class Rep, class Period >
+ bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept
+ {
+ if (!_exited())
+ {
+ int exit_code = 0;
+ auto b = boost::process::detail::api::wait_for(_child_handle, exit_code, rel_time, ec);
+ if (!b)
+ return false;
+ _exit_status->store(exit_code);
+ }
+ return true;
+ }
+
+ template< class Clock, class Duration >
+ bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, std::error_code & ec) noexcept
+ {
+ if (!_exited())
+ {
+ int exit_code = 0;
+ auto b = boost::process::detail::api::wait_until(_child_handle, exit_code, timeout_time, ec);
+ if (!b)
+ return false;
+ _exit_status->store(exit_code);
+ }
+ return true;
+ }
+
+
+ bool valid() const
+ {
+ return _child_handle.valid();
+ }
+ operator bool() const {return valid();}
+
+ bool in_group() const
+ {
+ return _child_handle.in_group();
+ }
+ bool in_group(std::error_code &ec) const noexcept
+ {
+ return _child_handle.in_group(ec);
+ }
+};
+
+
+
+}}
+#endif
+
diff --git a/boost/process/detail/config.hpp b/boost/process/detail/config.hpp
new file mode 100644
index 0000000000..2e280c1d53
--- /dev/null
+++ b/boost/process/detail/config.hpp
@@ -0,0 +1,99 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the 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 boost/process/config.hpp
+ *
+ * Defines various macros.
+ */
+
+#ifndef BOOST_PROCESS_DETAIL_CONFIG_HPP
+#define BOOST_PROCESS_DETAIL_CONFIG_HPP
+
+#include <boost/config.hpp>
+#include <system_error>
+#include <boost/system/api_config.hpp>
+
+#include <boost/process/exception.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <errno.h>
+#if defined(__GLIBC__)
+#include <features.h>
+#else
+extern char **environ;
+#endif
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/detail/winapi/get_last_error.hpp>
+#else
+#error "System API not supported by boost.process"
+#endif
+
+namespace boost { namespace process { namespace detail
+{
+
+#if !defined(BOOST_PROCESS_PIPE_SIZE)
+#define BOOST_PROCESS_PIPE_SIZE 1024
+#endif
+
+#if defined(BOOST_POSIX_API)
+namespace posix {namespace extensions {}}
+namespace api = posix;
+
+inline std::error_code get_last_error() noexcept
+{
+ return std::error_code(errno, std::system_category());
+}
+
+//copied from linux spec.
+#if defined (__USE_XOPEN_EXTENDED) && !defined (__USE_XOPEN2K8) || defined( __USE_BSD)
+#define BOOST_POSIX_HAS_VFORK 1
+#endif
+
+#elif defined(BOOST_WINDOWS_API)
+namespace windows {namespace extensions {}}
+namespace api = windows;
+
+inline std::error_code get_last_error() noexcept
+{
+ return std::error_code(::boost::detail::winapi::GetLastError(), std::system_category());
+}
+#endif
+
+inline void throw_last_error(const std::string & msg)
+{
+ throw process_error(get_last_error(), msg);
+}
+
+inline void throw_last_error()
+{
+ throw process_error(get_last_error());
+}
+
+
+template<typename Char> constexpr Char null_char();
+template<> constexpr char null_char<char> (){return '\0';}
+template<> constexpr wchar_t null_char<wchar_t> (){return L'\0';}
+
+template<typename Char> constexpr Char equal_sign();
+template<> constexpr char equal_sign<char> () {return '='; }
+template<> constexpr wchar_t equal_sign<wchar_t> () {return L'='; }
+
+template<typename Char> constexpr Char quote_sign();
+template<> constexpr char quote_sign<char> () {return '"'; }
+template<> constexpr wchar_t quote_sign<wchar_t> () {return L'"'; }
+
+template<typename Char> constexpr Char space_sign();
+template<> constexpr char space_sign<char> () {return ' '; }
+template<> constexpr wchar_t space_sign<wchar_t> () {return L' '; }
+
+
+}}}
+#endif
diff --git a/boost/process/detail/execute_impl.hpp b/boost/process/detail/execute_impl.hpp
new file mode 100644
index 0000000000..77722f78ca
--- /dev/null
+++ b/boost/process/detail/execute_impl.hpp
@@ -0,0 +1,284 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the 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 boost/process/execute.hpp
+ *
+ * Defines a function to execute a program.
+ */
+
+#ifndef BOOST_PROCESS_EXECUTE_HPP
+#define BOOST_PROCESS_EXECUTE_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/traits.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/executor.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/executor.hpp>
+#endif
+
+#include <boost/process/detail/basic_cmd.hpp>
+#include <boost/process/detail/handler.hpp>
+
+#include <boost/fusion/view.hpp>
+#include <boost/fusion/container.hpp>
+#include <boost/fusion/sequence.hpp>
+#include <boost/fusion/tuple.hpp>
+#include <boost/fusion/algorithm/transformation/filter_if.hpp>
+#include <boost/fusion/adapted/std_tuple.hpp>
+#include <boost/fusion/container/vector/convert.hpp>
+
+#include <type_traits>
+#include <utility>
+
+namespace boost { namespace process {
+
+class child;
+
+namespace detail {
+
+
+template<typename ...Args>
+struct has_wchar;
+
+template<typename First, typename ...Args>
+struct has_wchar<First, Args...>
+{
+ typedef has_wchar<Args...> next;
+ typedef typename std::remove_cv<
+ typename std::remove_reference<First>::type>::type res_type;
+
+ constexpr static bool my_value = is_wchar_t<res_type>::value;
+ constexpr static bool value = my_value || next::value;
+
+ typedef std::integral_constant<bool, value> type;
+};
+
+template<typename First>
+struct has_wchar<First>
+{
+ typedef typename std::remove_cv<
+ typename std::remove_reference<First>::type>::type res_type;
+
+ constexpr static bool value = is_wchar_t<res_type>::value;
+
+ typedef std::integral_constant<bool, value> type;
+};
+
+
+#if defined(BOOST_WINDOWS_API)
+//everything needs to be wchar_t
+#if defined(BOOST_NO_ANSI_APIS)
+template<bool has_wchar>
+struct required_char_type
+{
+ typedef wchar_t type;
+};
+#else
+template<bool has_wchar> struct required_char_type;
+template<> struct required_char_type<true>
+{
+ typedef wchar_t type;
+};
+template<> struct required_char_type<false>
+{
+ typedef char type;
+};
+#endif
+
+#elif defined(BOOST_POSIX_API)
+template<bool has_wchar>
+struct required_char_type
+{
+ typedef char type;
+};
+#endif
+
+template<typename ... Args>
+using required_char_type_t = typename required_char_type<
+ has_wchar<Args...>::value>::type;
+
+
+template<typename Iterator, typename End, typename ...Args>
+struct make_builders_from_view
+{
+ typedef boost::fusion::set<Args...> set;
+ typedef typename boost::fusion::result_of::deref<Iterator>::type ref_type;
+ typedef typename std::remove_reference<ref_type>::type res_type;
+ typedef typename initializer_tag<res_type>::type tag;
+ typedef typename initializer_builder<tag>::type builder_type;
+ typedef typename boost::fusion::result_of::has_key<set, builder_type> has_key;
+
+ typedef typename boost::fusion::result_of::next<Iterator>::type next_itr;
+ typedef typename make_builders_from_view<next_itr, End>::type next;
+
+ typedef typename
+ std::conditional<has_key::value,
+ typename make_builders_from_view<next_itr, End, Args...>::type,
+ typename make_builders_from_view<next_itr, End, Args..., builder_type>::type
+ >::type type;
+
+};
+
+template<typename Iterator, typename ...Args>
+struct make_builders_from_view<Iterator, Iterator, Args...>
+{
+ typedef boost::fusion::set<Args...> type;
+};
+
+template<typename Builders>
+struct builder_ref
+{
+ Builders &builders;
+ builder_ref(Builders & builders) : builders(builders) {};
+
+ template<typename T>
+ void operator()(T && value) const
+ {
+ typedef typename initializer_tag<typename std::remove_reference<T>::type>::type tag;
+ typedef typename initializer_builder<tag>::type builder_type;
+ boost::fusion::at_key<builder_type>(builders)(std::forward<T>(value));
+ }
+};
+
+template<typename T>
+struct get_initializers_result
+{
+ typedef typename T::result_type type;
+};
+
+template<>
+struct get_initializers_result<boost::fusion::void_>
+{
+ typedef boost::fusion::void_ type;
+};
+
+template<typename ...Args>
+struct helper_vector
+{
+
+};
+
+template<typename T, typename ...Stack>
+struct invoke_get_initializer_collect_keys;
+
+template<typename ...Stack>
+struct invoke_get_initializer_collect_keys<boost::fusion::vector<>, Stack...>
+{
+ typedef helper_vector<Stack...> type;
+};
+
+
+template<typename First, typename ...Args, typename ...Stack>
+struct invoke_get_initializer_collect_keys<boost::fusion::vector<First, Args...>, Stack...>
+{
+ typedef typename invoke_get_initializer_collect_keys<boost::fusion::vector<Args...>, Stack..., First>::type next;
+ typedef helper_vector<Stack...> stack_t;
+
+ typedef typename std::conditional<std::is_same<boost::fusion::void_, First>::value,
+ stack_t, next>::type type;
+
+
+};
+
+
+template<typename Keys>
+struct invoke_get_initializer;
+
+template<typename ...Args>
+struct invoke_get_initializer<helper_vector<Args...>>
+
+{
+ typedef boost::fusion::tuple<typename get_initializers_result<Args>::type...> result_type;
+
+ template<typename Sequence>
+ static result_type call(Sequence & seq)
+ {
+ return result_type(boost::fusion::at_key<Args>(seq).get_initializer()...);;
+ }
+};
+
+
+
+
+
+template<typename ...Args>
+inline boost::fusion::tuple<typename get_initializers_result<Args>::type...>
+ get_initializers(boost::fusion::set<Args...> & builders)
+{
+ //typedef boost::fusion::tuple<typename get_initializers_result<Args>::type...> return_type;
+ typedef typename invoke_get_initializer_collect_keys<boost::fusion::vector<Args...>>::type keys;
+ return invoke_get_initializer<keys>::call(builders);
+}
+
+
+template<typename Char, typename ... Args>
+inline child basic_execute_impl(Args && ... args)
+{
+ //create a tuple from the argument list
+ boost::fusion::tuple<typename std::remove_reference<Args>::type&...> tup(args...);
+
+ auto inits = boost::fusion::filter_if<
+ boost::process::detail::is_initializer<
+ typename std::remove_reference<
+ boost::mpl::_
+ >::type
+ >
+ >(tup);
+
+ auto others = boost::fusion::filter_if<
+ boost::mpl::not_<
+ boost::process::detail::is_initializer<
+ typename std::remove_reference<
+ boost::mpl::_
+ >::type
+ >
+ >
+ >(tup);
+
+ // typename detail::make_builders_from_view<decltype(others)>::type builders;
+
+ //typedef typename boost::fusion::result_of::as_vector<decltype(inits)>::type inits_t;
+ typedef typename boost::fusion::result_of::as_vector<decltype(others)>::type others_t;
+ // typedef decltype(others) others_t;
+ typedef typename ::boost::process::detail::make_builders_from_view<
+ typename boost::fusion::result_of::begin<others_t>::type,
+ typename boost::fusion::result_of::end <others_t>::type>::type builder_t;
+
+ builder_t builders;
+ ::boost::process::detail::builder_ref<builder_t> builder_ref(builders);
+
+ boost::fusion::for_each(others, builder_ref);
+ auto other_inits = ::boost::process::detail::get_initializers(builders);
+
+
+ boost::fusion::joint_view<decltype(other_inits), decltype(inits)> complete_inits(other_inits, inits);
+
+ auto exec = boost::process::detail::api::make_executor<Char>(complete_inits);
+ return exec();
+}
+
+template<typename ...Args>
+inline child execute_impl(Args&& ... args)
+{
+ typedef required_char_type_t<Args...> req_char_type;
+
+ return basic_execute_impl<req_char_type>(
+ boost::process::detail::char_converter_t<req_char_type, Args>::conv(
+ std::forward<Args>(args))...
+ );
+}
+
+}}}
+
+
+#endif
diff --git a/boost/process/detail/handler.hpp b/boost/process/detail/handler.hpp
new file mode 100644
index 0000000000..360c59f81a
--- /dev/null
+++ b/boost/process/detail/handler.hpp
@@ -0,0 +1,75 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_HANDLER_HPP_
+#define BOOST_PROCESS_DETAIL_HANDLER_HPP_
+
+#include <boost/process/detail/config.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/handler.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/handler.hpp>
+#endif
+
+
+namespace boost { namespace process { namespace detail {
+
+//extended handler base.
+typedef api::handler_base_ext handler;
+
+
+template <class Handler>
+struct on_setup_ : handler
+{
+ explicit on_setup_(Handler handler) : handler_(handler) {}
+
+ template <class Executor>
+ void on_setup(Executor &e)
+ {
+ handler_(e);
+ }
+private:
+ Handler handler_;
+};
+
+template <class Handler>
+struct on_error_ : handler
+{
+ explicit on_error_(Handler handler) : handler_(handler) {}
+
+ template <class Executor>
+ void on_error(Executor &e, const std::error_code &ec)
+ {
+ handler_(e, ec);
+ }
+private:
+ Handler handler_;
+};
+
+template <class Handler>
+struct on_success_ : handler
+{
+ explicit on_success_(Handler handler) : handler_(handler) {}
+
+ template <class Executor>
+ void on_success(Executor &e)
+ {
+ handler_(e);
+ }
+private:
+ Handler handler_;
+};
+
+}
+
+
+
+}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */
diff --git a/boost/process/detail/handler_base.hpp b/boost/process/detail/handler_base.hpp
new file mode 100644
index 0000000000..93a80520ee
--- /dev/null
+++ b/boost/process/detail/handler_base.hpp
@@ -0,0 +1,49 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_HANDLER_BASE_HPP
+#define BOOST_PROCESS_DETAIL_HANDLER_BASE_HPP
+
+#include <system_error>
+
+namespace boost { namespace process { namespace detail {
+
+template<template <class> class Template>
+struct make_handler_t
+{
+ constexpr make_handler_t() {}
+ template<typename Handler>
+ constexpr Template<Handler> operator()(Handler handler) const {return Template<Handler>(handler);}
+ template<typename Handler>
+ constexpr Template<Handler> operator= (Handler handler) const {return Template<Handler>(handler);}
+ template<typename Handler>
+ constexpr Template<Handler> operator+=(Handler handler) const {return Template<Handler>(handler);}
+};
+
+
+struct handler_base
+{
+ using resource_type = void;
+
+ template <class Executor>
+ void on_setup(Executor&) const {}
+
+ template <class Executor>
+ void on_error(Executor&, const std::error_code &) const {}
+
+ template <class Executor>
+ void on_success(Executor&) const {}
+
+};
+
+
+}}}
+
+#endif
diff --git a/boost/process/detail/on_exit.hpp b/boost/process/detail/on_exit.hpp
new file mode 100644
index 0000000000..d0fd5b8c84
--- /dev/null
+++ b/boost/process/detail/on_exit.hpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_ON_EXIT_HPP_
+#define BOOST_PROCESS_DETAIL_ON_EXIT_HPP_
+
+#include <boost/process/detail/config.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/on_exit.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/on_exit.hpp>
+#endif
+
+#include <future>
+#include <memory>
+
+namespace boost { namespace process { namespace detail {
+
+inline std::function<void(int, const std::error_code &)> on_exit_from_future(std::future<int> &f)
+{
+ std::shared_ptr<std::promise<int>> promise = std::make_shared<std::promise<int>>();
+ f = promise->get_future();
+ return [promise](int code, const std::error_code & ec)
+ {
+ if (ec)
+ promise->set_exception(
+ std::make_exception_ptr(process_error(ec, "on_exit failed with error"))
+ );
+ else
+ promise->set_value(code);
+ };
+}
+
+
+struct on_exit_
+{
+ api::on_exit_ operator= (const std::function<void(int, const std::error_code&)> & f) const {return f;}
+ api::on_exit_ operator()(const std::function<void(int, const std::error_code&)> & f) const {return f;}
+
+ api::on_exit_ operator= (std::future<int> &f) const {return on_exit_from_future(f);}
+ api::on_exit_ operator()(std::future<int> &f) const {return on_exit_from_future(f);}
+};
+
+}
+
+constexpr static ::boost::process::detail::on_exit_ on_exit{};
+
+
+}}
+#endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ON_EXIT_HPP_ */
diff --git a/boost/process/detail/posix/asio_fwd.hpp b/boost/process/detail/posix/asio_fwd.hpp
new file mode 100644
index 0000000000..06d5c19214
--- /dev/null
+++ b/boost/process/detail/posix/asio_fwd.hpp
@@ -0,0 +1,79 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_ASIO_FWD_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_ASIO_FWD_HPP_
+
+#include <memory>
+
+namespace boost { namespace asio {
+
+class mutable_buffer;
+class mutable_buffers_1;
+
+class const_buffer;
+class const_buffers_1;
+
+template<typename Allocator>
+class basic_streambuf;
+
+typedef basic_streambuf<std::allocator<char>> streambuf;
+class io_service;
+
+
+class signal_set_service;
+template <typename SignalSetService>
+
+class basic_signal_set;
+typedef basic_signal_set<signal_set_service> signal_set;
+
+template <typename Handler>
+class basic_yield_context;
+
+namespace posix {
+
+class stream_descriptor_service;
+
+template <typename StreamDesscriptorService>
+class basic_stream_descriptor;
+typedef basic_stream_descriptor<stream_descriptor_service> stream_descriptor;
+
+
+
+class object_handle_service;
+
+template <typename ObjectHandleService>
+class basic_object_handle;
+
+typedef basic_object_handle<object_handle_service> object_handle;
+
+} //posix
+} //asio
+
+namespace process { namespace detail { namespace posix {
+
+class async_pipe;
+
+template<typename T>
+struct async_in_buffer;
+
+template<int p1, int p2, typename Buffer>
+struct async_out_buffer;
+
+template<int p1, int p2, typename Type>
+struct async_out_future;
+
+} // posix
+} // detail
+
+using ::boost::process::detail::posix::async_pipe;
+
+} // process
+} // boost
+
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_POSIX_ASIO_FWD_HPP_ */
diff --git a/boost/process/detail/posix/async_handler.hpp b/boost/process/detail/posix/async_handler.hpp
new file mode 100644
index 0000000000..a61cff3372
--- /dev/null
+++ b/boost/process/detail/posix/async_handler.hpp
@@ -0,0 +1,40 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_POSIX_ASYNC_HANDLER_HPP_
+#define BOOST_PROCESS_POSIX_ASYNC_HANDLER_HPP_
+
+#include <boost/process/detail/posix/handler.hpp>
+#include <type_traits>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+struct require_io_service {};
+
+struct async_handler : handler_base_ext, require_io_service
+{
+};
+
+template<typename T>
+struct is_async_handler : std::is_base_of<async_handler, T> {};
+template<typename T>
+struct is_async_handler<T&> : std::is_base_of<async_handler, T> {};
+template<typename T>
+struct is_async_handler<const T&> : std::is_base_of<async_handler, T> {};
+
+template<typename T>
+struct does_require_io_service : std::is_base_of<require_io_service, T> {};
+
+template<typename T>
+struct does_require_io_service<T&> : std::is_base_of<require_io_service, T> {};
+
+template<typename T>
+struct does_require_io_service<const T&> : std::is_base_of<require_io_service, T> {};
+
+
+}}}}
+
+#endif /* BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_ */
diff --git a/boost/process/detail/posix/async_in.hpp b/boost/process/detail/posix/async_in.hpp
new file mode 100644
index 0000000000..9814c593f2
--- /dev/null
+++ b/boost/process/detail/posix/async_in.hpp
@@ -0,0 +1,95 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_IN_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_IN_HPP
+
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/posix/async_handler.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/process/async_pipe.hpp>
+#include <memory>
+#include <future>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+
+template<typename Buffer>
+struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext,
+ ::boost::process::detail::posix::require_io_service
+{
+ Buffer & buf;
+
+ std::shared_ptr<std::promise<void>> promise;
+ async_in_buffer operator>(std::future<void> & fut)
+ {
+ promise = std::make_shared<std::promise<void>>();
+ fut = promise->get_future(); return std::move(*this);
+ }
+
+ std::shared_ptr<boost::process::async_pipe> pipe;
+
+ async_in_buffer(Buffer & buf) : buf(buf)
+ {
+ }
+ template <typename Executor>
+ inline void on_success(Executor &exec)
+ {
+ auto pipe = this->pipe;
+ if (this->promise)
+ {
+ auto promise = this->promise;
+
+ boost::asio::async_write(*pipe, buf,
+ [pipe, promise](const boost::system::error_code & ec, std::size_t)
+ {
+ if (ec && (ec.value() != EBADF) && (ec.value() != EPERM) && (ec.value() != ENOENT))
+ {
+ std::error_code e(ec.value(), std::system_category());
+ promise->set_exception(std::make_exception_ptr(process_error(e)));
+ }
+ else
+ promise->set_value();
+ });
+ }
+ else
+ boost::asio::async_write(*pipe, buf,
+ [pipe](const boost::system::error_code&ec, std::size_t size){});
+
+ std::move(*pipe).source().close();
+
+ this->pipe = nullptr;
+ }
+
+ template<typename Executor>
+ void on_error(Executor &, const std::error_code &) const
+ {
+ std::move(*pipe).source().close();
+ }
+
+ template<typename Executor>
+ void on_setup(Executor & exec)
+ {
+ pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
+ }
+
+ template <typename Executor>
+ void on_exec_setup(Executor &exec)
+ {
+ if (::dup2(pipe->native_source(), STDIN_FILENO) == -1)
+ exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+
+ ::close(pipe->native_source());
+ }
+};
+
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/async_out.hpp b/boost/process/detail/posix/async_out.hpp
new file mode 100644
index 0000000000..b0f7876714
--- /dev/null
+++ b/boost/process/detail/posix/async_out.hpp
@@ -0,0 +1,170 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_OUT_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_OUT_HPP
+
+
+#include <boost/process/detail/posix/handler.hpp>
+#include <boost/asio/posix/stream_descriptor.hpp>
+#include <boost/asio/read.hpp>
+#include <boost/process/async_pipe.hpp>
+#include <istream>
+#include <memory>
+#include <exception>
+#include <future>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+
+inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::integral_constant<int, -1>)
+{
+ return ::dup2(handle, STDOUT_FILENO);
+}
+
+inline int apply_out_handles(int handle, std::integral_constant<int, 2>, std::integral_constant<int, -1>)
+{
+ return ::dup2(handle, STDERR_FILENO);
+}
+
+inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::integral_constant<int, 2>)
+{
+ if (::dup2(handle, STDOUT_FILENO) == -1)
+ return -1;
+ if (::dup2(handle, STDERR_FILENO) == -1)
+ return -1;
+
+ return 0;
+}
+
+template<int p1, int p2, typename Buffer>
+struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext,
+ ::boost::process::detail::posix::require_io_service
+{
+ Buffer & buf;
+
+ std::shared_ptr<boost::process::async_pipe> pipe;
+
+
+ async_out_buffer(Buffer & buf) : buf(buf)
+ {
+ }
+
+ template <typename Executor>
+ inline void on_success(Executor &exec)
+ {
+ auto pipe = this->pipe;
+ boost::asio::async_read(*pipe, buf,
+ [pipe](const boost::system::error_code&, std::size_t size){});
+
+ this->pipe = nullptr;
+ std::move(*pipe).sink().close();
+ }
+
+ template<typename Executor>
+ void on_error(Executor &, const std::error_code &) const
+ {
+ std::move(*pipe).sink().close();
+ }
+
+ template<typename Executor>
+ void on_setup(Executor & exec)
+ {
+ pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
+ }
+
+
+ template <typename Executor>
+ void on_exec_setup(Executor &exec)
+ {
+ int res = apply_out_handles(pipe->native_sink(),
+ std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
+ if (res == -1)
+ exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+
+ ::close(pipe->native_sink());
+ }
+};
+
+
+
+
+template<int p1, int p2, typename Type>
+struct async_out_future : ::boost::process::detail::posix::handler_base_ext,
+ ::boost::process::detail::posix::require_io_service
+{
+ std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>();
+
+ std::shared_ptr<boost::asio::streambuf> buffer = std::make_shared<boost::asio::streambuf>();
+
+ std::shared_ptr<boost::process::async_pipe> pipe;
+
+ async_out_future(std::future<Type> & fut)
+ {
+ fut = promise->get_future();
+ }
+ template <typename Executor>
+ inline void on_success(Executor &exec)
+ {
+ auto pipe = this->pipe;
+
+ auto buffer = this->buffer;
+ auto promise = this->promise;
+
+ boost::asio::async_read(*pipe, *buffer,
+ [pipe, buffer, promise](const boost::system::error_code& ec, std::size_t size)
+ {
+ if (ec && (ec.value() != ENOENT))
+ {
+ std::error_code e(ec.value(), std::system_category());
+ promise->set_exception(std::make_exception_ptr(process_error(e)));
+ }
+ else
+ {
+ std::istream is (buffer.get());
+ Type arg;
+ arg.resize(buffer->size());
+ is.read(&*arg.begin(), buffer->size());
+ promise->set_value(std::move(arg));
+ }
+ });
+
+ std::move(*pipe).sink().close();
+ this->pipe = nullptr;
+ }
+
+ template<typename Executor>
+ void on_error(Executor &, const std::error_code &) const
+ {
+ std::move(*pipe).sink().close();
+ }
+
+ template<typename Executor>
+ void on_setup(Executor & exec)
+ {
+ pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
+ }
+
+ template <typename Executor>
+ void on_exec_setup(Executor &exec)
+ {
+
+ int res = apply_out_handles(pipe->native_sink(),
+ std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
+ if (res == -1)
+ exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+
+ ::close(pipe->native_sink());
+ }
+
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/async_pipe.hpp b/boost/process/detail/posix/async_pipe.hpp
new file mode 100644
index 0000000000..d849559c20
--- /dev/null
+++ b/boost/process/detail/posix/async_pipe.hpp
@@ -0,0 +1,355 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_PIPE_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_PIPE_HPP_
+
+
+#include <boost/process/detail/posix/basic_pipe.hpp>
+#include <boost/asio/posix/stream_descriptor.hpp>
+#include <system_error>
+#include <string>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+class async_pipe
+{
+ ::boost::asio::posix::stream_descriptor _source;
+ ::boost::asio::posix::stream_descriptor _sink ;
+public:
+ typedef int native_handle_type;
+ typedef ::boost::asio::posix::stream_descriptor handle_type;
+
+ inline async_pipe(boost::asio::io_service & ios) : async_pipe(ios, ios) {}
+
+ inline async_pipe(boost::asio::io_service & ios_source,
+ boost::asio::io_service & ios_sink) : _source(ios_source), _sink(ios_sink)
+ {
+ int fds[2];
+ if (::pipe(fds) == -1)
+ boost::process::detail::throw_last_error("pipe(2) failed");
+
+ _source.assign(fds[0]);
+ _sink .assign(fds[1]);
+ };
+ inline async_pipe(boost::asio::io_service & ios, const std::string & name)
+ : async_pipe(ios, ios, name) {}
+
+ inline async_pipe(boost::asio::io_service & ios_source,
+ boost::asio::io_service & io_sink, const std::string & name);
+ inline async_pipe(const async_pipe& lhs);
+ async_pipe(async_pipe&& lhs) : _source(std::move(lhs._source)), _sink(std::move(lhs._sink))
+ {
+ lhs._source.assign (-1);
+ lhs._sink .assign (-1);
+ }
+
+ template<class CharT, class Traits = std::char_traits<CharT>>
+ explicit async_pipe(::boost::asio::io_service & ios_source,
+ ::boost::asio::io_service & ios_sink,
+ const basic_pipe<CharT, Traits> & p)
+ : _source(ios_source, p.native_source()), _sink(ios_sink, p.native_sink())
+ {
+ }
+
+ template<class CharT, class Traits = std::char_traits<CharT>>
+ explicit async_pipe(boost::asio::io_service & ios, const basic_pipe<CharT, Traits> & p)
+ : async_pipe(ios, ios, p)
+ {
+ }
+
+ template<class CharT, class Traits = std::char_traits<CharT>>
+ inline async_pipe& operator=(const basic_pipe<CharT, Traits>& p);
+ inline async_pipe& operator=(const async_pipe& rhs);
+
+ inline async_pipe& operator=(async_pipe&& lhs);
+
+ ~async_pipe()
+ {
+ if (_sink .native() != -1)
+ ::close(_sink.native());
+ if (_source.native() != -1)
+ ::close(_source.native());
+ }
+
+ template<class CharT, class Traits = std::char_traits<CharT>>
+ inline explicit operator basic_pipe<CharT, Traits>() const;
+
+ void cancel()
+ {
+ if (_sink.is_open())
+ _sink.cancel();
+ if (_source.is_open())
+ _source.cancel();
+ }
+
+ void close()
+ {
+ if (_sink.is_open())
+ _sink.close();
+ if (_source.is_open())
+ _source.close();
+ }
+ void close(boost::system::error_code & ec)
+ {
+ if (_sink.is_open())
+ _sink.close(ec);
+ if (_source.is_open())
+ _source.close(ec);
+ }
+
+
+ bool is_open() const
+ {
+ return _sink.is_open() || _source.is_open();
+ }
+ void async_close()
+ {
+ if (_sink.is_open())
+ _sink.get_io_service(). post([this]{_sink.close();});
+ if (_source.is_open())
+ _source.get_io_service().post([this]{_source.close();});
+ }
+
+ template<typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence & buffers)
+ {
+ return _source.read_some(buffers);
+ }
+ template<typename MutableBufferSequence>
+ std::size_t write_some(const MutableBufferSequence & buffers)
+ {
+ return _sink.write_some(buffers);
+ }
+
+ native_handle_type native_source() const {return const_cast<boost::asio::posix::stream_descriptor&>(_source).native();}
+ native_handle_type native_sink () const {return const_cast<boost::asio::posix::stream_descriptor&>(_sink ).native();}
+
+ template<typename MutableBufferSequence,
+ typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(
+ ReadHandler, void(boost::system::error_code, std::size_t))
+ async_read_some(
+ const MutableBufferSequence & buffers,
+ ReadHandler &&handler)
+ {
+ _source.async_read_some(buffers, std::forward<ReadHandler>(handler));
+ }
+
+ template<typename ConstBufferSequence,
+ typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(
+ WriteHandler, void(boost::system::error_code, std::size_t))
+ async_write_some(
+ const ConstBufferSequence & buffers,
+ WriteHandler&& handler)
+ {
+ _sink.async_write_some(buffers, std::forward<WriteHandler>(handler));
+ }
+
+
+ const handle_type & sink () const & {return _sink;}
+ const handle_type & source() const & {return _source;}
+
+ handle_type && sink() && { return std::move(_sink); }
+ handle_type && source()&& { return std::move(_source); }
+
+ handle_type source(::boost::asio::io_service& ios) &&
+ {
+ ::boost::asio::posix::stream_descriptor stolen(ios, _source.release());
+ return stolen;
+ }
+ handle_type sink (::boost::asio::io_service& ios) &&
+ {
+ ::boost::asio::posix::stream_descriptor stolen(ios, _sink.release());
+ return stolen;
+ }
+
+ handle_type source(::boost::asio::io_service& ios) const &
+ {
+ auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native();
+ return ::boost::asio::posix::stream_descriptor(ios, ::dup(source_in));
+ }
+ handle_type sink (::boost::asio::io_service& ios) const &
+ {
+ auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native();
+ return ::boost::asio::posix::stream_descriptor(ios, ::dup(sink_in));
+ }
+};
+
+
+async_pipe::async_pipe(boost::asio::io_service & ios_source,
+ boost::asio::io_service & ios_sink,
+ const std::string & name) : _source(ios_source), _sink(ios_sink)
+{
+ auto fifo = mkfifo(name.c_str(), 0666 );
+
+ if (fifo != 0)
+ boost::process::detail::throw_last_error("mkfifo() failed");
+
+
+ int read_fd = open(name.c_str(), O_RDWR);
+
+ if (read_fd == -1)
+ boost::process::detail::throw_last_error();
+
+ int write_fd = dup(read_fd);
+
+ if (write_fd == -1)
+ boost::process::detail::throw_last_error();
+
+ _source.assign(read_fd);
+ _sink .assign(write_fd);
+}
+
+async_pipe::async_pipe(const async_pipe & p) :
+ _source(const_cast<async_pipe&>(p)._source.get_io_service()),
+ _sink( const_cast<async_pipe&>(p)._sink.get_io_service())
+{
+
+ //cannot get the handle from a const object.
+ auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native();
+ auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native();
+ if (source_in == -1)
+ _source.assign(-1);
+ else
+ {
+ _source.assign(::dup(source_in));
+ if (_source.native()== -1)
+ ::boost::process::detail::throw_last_error("dup()");
+ }
+
+ if (sink_in == -1)
+ _sink.assign(-1);
+ else
+ {
+ _sink.assign(::dup(sink_in));
+ if (_sink.native() == -1)
+ ::boost::process::detail::throw_last_error("dup()");
+ }
+}
+
+async_pipe& async_pipe::operator=(const async_pipe & p)
+{
+ int source;
+ int sink;
+
+ //cannot get the handle from a const object.
+ auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native();
+ auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native();
+ if (source_in == -1)
+ source = -1;
+ else
+ {
+ source = ::dup(source_in);
+ if (source == -1)
+ ::boost::process::detail::throw_last_error("dup()");
+ }
+
+ if (sink_in == -1)
+ sink = -1;
+ else
+ {
+ sink = ::dup(sink_in);
+ if (sink == -1)
+ ::boost::process::detail::throw_last_error("dup()");
+ }
+ _source.assign(source);
+ _sink. assign(sink);
+
+ return *this;
+}
+
+async_pipe& async_pipe::operator=(async_pipe && lhs)
+{
+ if (_source.native_handle() == -1)
+ ::close(_source.native());
+
+ if (_sink.native_handle() == -1)
+ ::close(_sink.native());
+
+ _source.assign(lhs._source.native_handle());
+ _sink .assign(lhs._sink .native_handle());
+ lhs._source.assign(-1);
+ lhs._sink .assign(-1);
+ return *this;
+}
+
+template<class CharT, class Traits>
+async_pipe::operator basic_pipe<CharT, Traits>() const
+{
+ int source;
+ int sink;
+
+ //cannot get the handle from a const object.
+ auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native();
+ auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native();
+
+
+ if (source_in == -1)
+ source = -1;
+ else
+ {
+ source = ::dup(source_in);
+ if (source == -1)
+ ::boost::process::detail::throw_last_error("dup()");
+ }
+
+ if (sink_in == -1)
+ sink = -1;
+ else
+ {
+ sink = ::dup(sink_in);
+ if (sink == -1)
+ ::boost::process::detail::throw_last_error("dup()");
+ }
+
+ return basic_pipe<CharT, Traits>{source, sink};
+}
+
+
+inline bool operator==(const async_pipe & lhs, const async_pipe & rhs)
+{
+ return compare_handles(lhs.native_source(), rhs.native_source()) &&
+ compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+inline bool operator!=(const async_pipe & lhs, const async_pipe & rhs)
+{
+ return !compare_handles(lhs.native_source(), rhs.native_source()) ||
+ !compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+template<class Char, class Traits>
+inline bool operator==(const async_pipe & lhs, const basic_pipe<Char, Traits> & rhs)
+{
+ return compare_handles(lhs.native_source(), rhs.native_source()) &&
+ compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+template<class Char, class Traits>
+inline bool operator!=(const async_pipe & lhs, const basic_pipe<Char, Traits> & rhs)
+{
+ return !compare_handles(lhs.native_source(), rhs.native_source()) ||
+ !compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+template<class Char, class Traits>
+inline bool operator==(const basic_pipe<Char, Traits> & lhs, const async_pipe & rhs)
+{
+ return compare_handles(lhs.native_source(), rhs.native_source()) &&
+ compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+template<class Char, class Traits>
+inline bool operator!=(const basic_pipe<Char, Traits> & lhs, const async_pipe & rhs)
+{
+ return !compare_handles(lhs.native_source(), rhs.native_source()) ||
+ !compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+}}}}
+
+#endif /* INCLUDE_BOOST_PIPE_DETAIL_WINDOWS_ASYNC_PIPE_HPP_ */
diff --git a/boost/process/detail/posix/basic_cmd.hpp b/boost/process/detail/posix/basic_cmd.hpp
new file mode 100644
index 0000000000..eefcc5c53f
--- /dev/null
+++ b/boost/process/detail/posix/basic_cmd.hpp
@@ -0,0 +1,177 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_BASIC_CMD_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_BASIC_CMD_HPP_
+
+#include <boost/process/detail/posix/handler.hpp>
+#include <boost/process/detail/posix/cmd.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/process/shell.hpp>
+#include <boost/algorithm/string/trim.hpp>
+#include <boost/algorithm/string/join.hpp>
+#include <string>
+#include <vector>
+
+namespace boost
+{
+namespace process
+{
+namespace detail
+{
+namespace posix
+{
+
+
+inline std::string build_cmd_shell(const std::string & exe, std::vector<std::string> && data)
+{
+ std::string st = exe;
+ for (auto & arg : data)
+ {
+ boost::replace_all(arg, "\"", "\\\"");
+
+ auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
+ if (it != arg.end())//ok, contains spaces.
+ {
+ //the first one is put directly onto the output,
+ //because then I don't have to copy the whole string
+ arg.insert(arg.begin(), '"' );
+ arg += '"'; //thats the post one.
+ }
+
+ if (!st.empty())//first one does not need a preceeding space
+ st += ' ';
+
+ st += arg;
+ }
+ return st ;
+}
+
+inline std::vector<std::string> build_args(const std::string & data)
+{
+ std::vector<std::string> st;
+
+ typedef std::string::const_iterator itr_t;
+
+ //normal quotes outside can be stripped, inside ones marked as \" will be replaced.
+ auto make_entry = [](const itr_t & begin, const itr_t & end)
+ {
+ std::string data;
+ if ((*begin == '"') && (*(end-1) == '"'))
+ data.assign(begin+1, end-1);
+ else
+ data.assign(begin, end);
+
+ boost::replace_all(data, "\\\"", "\"");
+ return data;
+
+ };
+
+ bool in_quote = false;
+
+ auto part_beg = data.cbegin();
+ auto itr = data.cbegin();
+
+ for (; itr != data.cend(); itr++)
+ {
+ if (*itr == '"')
+ in_quote ^= true;
+
+ if (!in_quote && (*itr == ' '))
+ {
+ //alright, got a space
+
+ if ((itr != data.cbegin()) && (*(itr -1) != ' ' ))
+ st.push_back(make_entry(part_beg, itr));
+
+ part_beg = itr+1;
+ }
+ }
+ if (part_beg != itr)
+ st.emplace_back(make_entry(part_beg, itr));
+
+
+ return st;
+}
+
+template<typename Char>
+struct exe_cmd_init;
+
+template<>
+struct exe_cmd_init<char> : boost::process::detail::api::handler_base_ext
+{
+ exe_cmd_init(const exe_cmd_init & ) = delete;
+ exe_cmd_init(exe_cmd_init && ) = default;
+ exe_cmd_init(std::string && exe, std::vector<std::string> && args)
+ : exe(std::move(exe)), args(std::move(args)) {};
+ template <class Executor>
+ void on_setup(Executor& exec)
+ {
+ if (exe.empty()) //cmd style
+ {
+ exec.exe = args.front().c_str();
+ exec.cmd_style = true;
+ }
+ else
+ exec.exe = &exe.front();
+
+
+ if (!args.empty())
+ {
+ cmd_impl = make_cmd();
+ exec.cmd_line = cmd_impl.data();
+ }
+ }
+ static exe_cmd_init exe_args(std::string && exe, std::vector<std::string> && args) {return exe_cmd_init(std::move(exe), std::move(args));}
+ static exe_cmd_init cmd (std::string && cmd)
+ {
+ auto args = build_args(cmd);
+ return exe_cmd_init({}, std::move(args));
+ }
+
+ static exe_cmd_init exe_args_shell(std::string&& exe, std::vector<std::string> && args)
+ {
+ auto cmd = build_cmd_shell(std::move(exe), std::move(args));
+
+ std::vector<std::string> args_ = {"-c", std::move(cmd)};
+ std::string sh = shell().string();
+
+ return exe_cmd_init(std::move(sh), std::move(args_));
+ }
+ static exe_cmd_init cmd_shell(std::string&& cmd)
+ {
+ std::vector<std::string> args = {"-c", "\"" + cmd + "\""};
+ std::string sh = shell().string();
+
+ return exe_cmd_init(
+ std::move(sh),
+ {std::move(args)});
+ }
+private:
+ inline std::vector<char*> make_cmd();
+ std::string exe;
+ std::vector<std::string> args;
+ std::vector<char*> cmd_impl;
+};
+
+std::vector<char*> exe_cmd_init<char>::make_cmd()
+{
+ std::vector<char*> vec;
+ if (!exe.empty())
+ vec.push_back(&exe.front());
+
+ for (auto & v : args)
+ vec.push_back(&v.front());
+
+ vec.push_back(nullptr);
+
+ return vec;
+}
+
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/basic_pipe.hpp b/boost/process/detail/posix/basic_pipe.hpp
new file mode 100644
index 0000000000..77fc90a4c1
--- /dev/null
+++ b/boost/process/detail/posix/basic_pipe.hpp
@@ -0,0 +1,193 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_POSIX_PIPE_HPP
+#define BOOST_PROCESS_POSIX_PIPE_HPP
+
+
+#include <boost/filesystem.hpp>
+#include <boost/process/detail/posix/compare_handles.hpp>
+#include <system_error>
+#include <array>
+#include <unistd.h>
+#include <fcntl.h>
+#include <memory>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+
+template<class CharT, class Traits = std::char_traits<CharT>>
+class basic_pipe
+{
+ int _source = -1;
+ int _sink = -1;
+public:
+ explicit basic_pipe(int source, int sink) : _source(source), _sink(sink) {}
+ explicit basic_pipe(int source, int sink, const std::string & name) : _source(source), _sink(sink) {}
+ typedef CharT char_type ;
+ typedef Traits traits_type;
+ typedef typename Traits::int_type int_type ;
+ typedef typename Traits::pos_type pos_type ;
+ typedef typename Traits::off_type off_type ;
+ typedef int native_handle_type;
+
+ basic_pipe()
+ {
+ int fds[2];
+ if (::pipe(fds) == -1)
+ boost::process::detail::throw_last_error("pipe(2) failed");
+
+ _source = fds[0];
+ _sink = fds[1];
+ }
+ inline basic_pipe(const basic_pipe& rhs);
+ explicit inline basic_pipe(const std::string& name);
+ basic_pipe(basic_pipe&& lhs) : _source(lhs._source), _sink(lhs._sink)
+ {
+ lhs._source = -1;
+ lhs._sink = -1;
+ }
+ inline basic_pipe& operator=(const basic_pipe& );
+ basic_pipe& operator=(basic_pipe&& lhs)
+ {
+ _source = lhs._source;
+ _sink = lhs._sink ;
+
+ lhs._source = -1;
+ lhs._sink = -1;
+
+ return *this;
+ }
+ ~basic_pipe()
+ {
+ if (_sink != -1)
+ ::close(_sink);
+ if (_source != -1)
+ ::close(_source);
+ }
+ native_handle_type native_source() const {return _source;}
+ native_handle_type native_sink () const {return _sink;}
+
+ void assign_source(native_handle_type h) { _source = h;}
+ void assign_sink (native_handle_type h) { _sink = h;}
+
+
+
+
+ int_type write(const char_type * data, int_type count)
+ {
+ auto write_len = ::write(_sink, data, count * sizeof(char_type));
+ if (write_len == -1)
+ ::boost::process::detail::throw_last_error();
+
+ return write_len;
+ }
+ int_type read(char_type * data, int_type count)
+ {
+ auto read_len = ::read(_source, data, count * sizeof(char_type));
+ if (read_len == -1)
+ ::boost::process::detail::throw_last_error();
+
+ return read_len;
+ }
+
+ bool is_open()
+ {
+ return (_source != -1) ||
+ (_sink != -1);
+ }
+
+ void close()
+ {
+ ::close(_source);
+ ::close(_sink);
+ _source = -1;
+ _sink = -1;
+ }
+};
+
+template<class CharT, class Traits>
+basic_pipe<CharT, Traits>::basic_pipe(const basic_pipe & rhs)
+{
+ if (rhs._source != -1)
+ {
+ _source = ::dup(rhs._source);
+ if (_source == -1)
+ ::boost::process::detail::throw_last_error("dup() failed");
+ }
+ if (rhs._sink != -1)
+ {
+ _sink = ::dup(rhs._sink);
+ if (_sink == -1)
+ ::boost::process::detail::throw_last_error("dup() failed");
+
+ }
+}
+
+template<class CharT, class Traits>
+basic_pipe<CharT, Traits> &basic_pipe<CharT, Traits>::operator=(const basic_pipe & rhs)
+{
+ if (rhs._source != -1)
+ {
+ _source = ::dup(rhs._source);
+ if (_source == -1)
+ ::boost::process::detail::throw_last_error("dup() failed");
+ }
+ if (rhs._sink != -1)
+ {
+ _sink = ::dup(rhs._sink);
+ if (_sink == -1)
+ ::boost::process::detail::throw_last_error("dup() failed");
+
+ }
+ return *this;
+}
+
+
+template<class CharT, class Traits>
+basic_pipe<CharT, Traits>::basic_pipe(const std::string & name)
+{
+ auto fifo = mkfifo(name.c_str(), 0666 );
+
+ if (fifo != 0)
+ boost::process::detail::throw_last_error("mkfifo() failed");
+
+
+ int read_fd = open(name.c_str(), O_RDWR);
+
+ if (read_fd == -1)
+ boost::process::detail::throw_last_error();
+
+ int write_fd = dup(read_fd);
+
+ if (write_fd == -1)
+ boost::process::detail::throw_last_error();
+
+ _sink = write_fd;
+ _source = read_fd;
+ ::unlink(name.c_str());
+}
+
+template<class Char, class Traits>
+inline bool operator==(const basic_pipe<Char, Traits> & lhs, const basic_pipe<Char, Traits> & rhs)
+{
+ return compare_handles(lhs.native_source(), rhs.native_source()) &&
+ compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+template<class Char, class Traits>
+inline bool operator!=(const basic_pipe<Char, Traits> & lhs, const basic_pipe<Char, Traits> & rhs)
+{
+ return !compare_handles(lhs.native_source(), rhs.native_source()) ||
+ !compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/child_handle.hpp b/boost/process/detail/posix/child_handle.hpp
new file mode 100644
index 0000000000..44ec43ea68
--- /dev/null
+++ b/boost/process/detail/posix/child_handle.hpp
@@ -0,0 +1,60 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_POSIX_CHILD_HPP
+#define BOOST_PROCESS_POSIX_CHILD_HPP
+
+#include <utility>
+#include <system_error>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+typedef ::pid_t pid_t;
+
+struct child_handle
+{
+ int pid {-1};
+ explicit child_handle(int pid) : pid(pid)
+ {}
+
+ child_handle() = default;
+ ~child_handle() = default;
+
+ child_handle(const child_handle & c) = delete;
+ child_handle(child_handle && c) : pid(c.pid)
+ {
+ c.pid = -1;
+ }
+ child_handle &operator=(const child_handle & c) = delete;
+ child_handle &operator=(child_handle && c)
+ {
+ pid = c.pid;
+ c.pid = -1;
+ return *this;
+ }
+
+ int id() const
+ {
+ return pid;
+ }
+ bool in_group() const {return true;}
+ bool in_group(std::error_code &ec) const noexcept {return true;}
+
+ typedef int process_handle_t;
+ process_handle_t process_handle() const { return pid; }
+
+ bool valid() const
+ {
+ return pid != -1;
+ }
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/close_in.hpp b/boost/process/detail/posix/close_in.hpp
new file mode 100644
index 0000000000..74cffd6729
--- /dev/null
+++ b/boost/process/detail/posix/close_in.hpp
@@ -0,0 +1,30 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_IN_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_IN_HPP
+
+
+#include <boost/process/detail/posix/handler.hpp>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+struct close_in : handler_base_ext
+{
+ template <class Executor>
+ void on_exec_setup(Executor &e) const
+ {
+ if (::close(STDIN_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "close() failed");
+ }
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/close_out.hpp b/boost/process/detail/posix/close_out.hpp
new file mode 100644
index 0000000000..f3659f5544
--- /dev/null
+++ b/boost/process/detail/posix/close_out.hpp
@@ -0,0 +1,55 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_CLOSE_OUT_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_CLOSE_OUT_HPP
+
+
+#include <boost/process/detail/posix/handler.hpp>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+template<int p1, int p2>
+struct close_out : handler_base_ext
+{
+ template <class Executor>
+ inline void on_exec_setup(Executor &e) const;
+};
+
+template<>
+template<typename Executor>
+void close_out<1,-1>::on_exec_setup(Executor &e) const
+{
+ if (::close(STDOUT_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "close() failed");
+
+}
+
+template<>
+template<typename Executor>
+void close_out<2,-1>::on_exec_setup(Executor &e) const
+{
+ if (::close(STDERR_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "close() failed");
+}
+
+template<>
+template<typename Executor>
+void close_out<1,2>::on_exec_setup(Executor &e) const
+{
+ if (::close(STDOUT_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "close() failed");
+
+ if (::close(STDERR_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "close() failed");
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/cmd.hpp b/boost/process/detail/posix/cmd.hpp
new file mode 100644
index 0000000000..ab4f4fb066
--- /dev/null
+++ b/boost/process/detail/posix/cmd.hpp
@@ -0,0 +1,104 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_CMD_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_CMD_HPP_
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/posix/handler.hpp>
+#include <string>
+#include <vector>
+
+namespace boost
+{
+namespace process
+{
+namespace detail
+{
+namespace posix
+{
+
+
+template<typename Char>
+inline std::vector<std::basic_string<Char>> build_cmd(const std::basic_string<Char> & value)
+{
+ std::vector<std::basic_string<Char>> ret;
+
+ bool in_quotes = false;
+ auto beg = value.begin();
+ for (auto itr = value.begin(); itr != value.end(); itr++)
+ {
+ if (*itr == quote_sign<Char>())
+ in_quotes = !in_quotes;
+
+ if (!in_quotes && (*itr == space_sign<Char>()))
+ {
+ if (itr != beg)
+ {
+ ret.emplace_back(beg, itr);
+ beg = itr + 1;
+ }
+ }
+ }
+ if (beg != value.end())
+ ret.emplace_back(beg, value.end());
+
+ return ret;
+}
+
+template<typename Char>
+struct cmd_setter_ : handler_base_ext
+{
+ typedef Char value_type;
+ typedef std::basic_string<value_type> string_type;
+
+ cmd_setter_(string_type && cmd_line) : _cmd_line(api::build_cmd(std::move(cmd_line))) {}
+ cmd_setter_(const string_type & cmd_line) : _cmd_line(api::build_cmd(cmd_line)) {}
+ template <class Executor>
+ void on_setup(Executor& exec)
+ {
+ exec.exe = _cmd_impl.front();
+ exec.cmd_line = &_cmd_impl.front();
+ exec.cmd_style = true;
+ }
+ string_type str() const
+ {
+ string_type ret;
+ std::size_t size = 0;
+ for (auto & cmd : _cmd_line)
+ size += cmd.size() + 1;
+ ret.reserve(size -1);
+
+ for (auto & cmd : _cmd_line)
+ {
+ if (!ret.empty())
+ ret += equal_sign<Char>();
+ ret += cmd;
+ }
+ return ret;
+ }
+private:
+ static inline std::vector<Char*> make_cmd(std::vector<string_type> & args);
+ std::vector<string_type> _cmd_line;
+ std::vector<Char*> _cmd_impl = make_cmd(_cmd_line);
+};
+
+template<typename Char>
+std::vector<Char*> cmd_setter_<Char>::make_cmd(std::vector<std::basic_string<Char>> & args)
+{
+ std::vector<Char*> vec;
+
+ for (auto & v : args)
+ vec.push_back(&v.front());
+
+ vec.push_back(nullptr);
+
+ return vec;
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/compare_handles.hpp b/boost/process/detail/posix/compare_handles.hpp
new file mode 100644
index 0000000000..634757215f
--- /dev/null
+++ b/boost/process/detail/posix/compare_handles.hpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_COMPARE_HANDLES_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_COMPARE_HANDLES_HPP_
+
+
+#include <boost/process/detail/config.hpp>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+
+inline bool compare_handles(int lhs, int rhs)
+{
+
+ if ((lhs == -1) || (rhs == -1))
+ return false;
+
+ if (lhs == rhs)
+ return true;
+
+ struct stat stat1, stat2;
+ if(fstat(lhs, &stat1) < 0) ::boost::process::detail::throw_last_error("fstat() failed");
+ if(fstat(rhs, &stat2) < 0) ::boost::process::detail::throw_last_error("fstat() failed");
+
+ return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino);
+}
+
+
+
+
+
+}}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_POSIX_COMPARE_HANDLES_HPP_ */
diff --git a/boost/process/detail/posix/env_init.hpp b/boost/process/detail/posix/env_init.hpp
new file mode 100644
index 0000000000..4d01cdad11
--- /dev/null
+++ b/boost/process/detail/posix/env_init.hpp
@@ -0,0 +1,41 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_ENV_INIT_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_ENV_INIT_HPP_
+
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/posix/handler.hpp>
+#include <boost/process/environment.hpp>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+template<typename Char>
+struct env_init;
+
+template<>
+struct env_init<char> : handler_base_ext
+{
+ boost::process::environment env;
+
+ env_init(boost::process::environment && env) : env(std::move(env)) {};
+ env_init(const boost::process::environment & env) : env(env) {};
+
+
+ template <class Executor>
+ void on_setup(Executor &exec) const
+ {
+ exec.env = env._env_impl;
+ }
+
+};
+
+}}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_INIT_HPP_ */
diff --git a/boost/process/detail/posix/environment.hpp b/boost/process/detail/posix/environment.hpp
new file mode 100644
index 0000000000..1011c03a9d
--- /dev/null
+++ b/boost/process/detail/posix/environment.hpp
@@ -0,0 +1,322 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <boost/process/detail/config.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <boost/process/locale.hpp>
+
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+template<typename Char>
+class native_environment_impl
+{
+ static std::vector<std::basic_string<Char>> _load()
+ {
+ std::vector<std::basic_string<Char>> val;
+ auto p = environ;
+ while (*p != nullptr)
+ {
+ std::string str = *p;
+ val.push_back(::boost::process::detail::convert(str));
+ p++;
+ }
+ return val;
+ }
+ static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & vec)
+ {
+ std::vector<Char*> val;
+ val.resize(vec.size() + 1);
+ std::transform(vec.begin(), vec.end(), val.begin(),
+ [](std::basic_string<Char> & str)
+ {
+ return &str.front();
+ });
+ val.back() = nullptr;
+ return val;
+ }
+ std::vector<std::basic_string<Char>> _buffer = _load();
+ std::vector<Char*> _impl = _load_var(_buffer);
+public:
+ using char_type = Char;
+ using pointer_type = const char_type*;
+ using string_type = std::basic_string<char_type>;
+ using native_handle_type = char_type **;
+
+ void reload()
+ {
+ _buffer = _load();
+ _impl = _load_var(_buffer);
+ }
+
+ string_type get(const pointer_type id) { return get(string_type(id)); }
+ void set(const pointer_type id, const pointer_type value)
+ {
+ set(string_type(id), string_type(value));
+ }
+ void reset(const pointer_type id) { reset(string_type(id)); }
+
+ string_type get(const string_type & id)
+ {
+ std::string id_c = ::boost::process::detail::convert(id);
+ std::string g = ::getenv(id_c.c_str());
+ return ::boost::process::detail::convert(g.c_str());
+ }
+ void set(const string_type & id, const string_type & value)
+ {
+ std::string id_c = ::boost::process::detail::convert(id.c_str());
+ std::string value_c = ::boost::process::detail::convert(value.c_str());
+ auto res = ::setenv(id_c.c_str(), value_c.c_str(), true);
+ if (res != 0)
+ boost::process::detail::throw_last_error();
+ }
+ void reset(const string_type & id)
+ {
+ std::string id_c = ::boost::process::detail::convert(id.c_str());
+ auto res = ::unsetenv(id_c.c_str());
+ if (res != 0)
+ ::boost::process::detail::throw_last_error();
+ }
+
+ native_environment_impl() = default;
+ native_environment_impl(const native_environment_impl& ) = delete;
+ native_environment_impl(native_environment_impl && ) = default;
+ native_environment_impl & operator=(const native_environment_impl& ) = delete;
+ native_environment_impl & operator=(native_environment_impl && ) = default;
+ native_handle_type _env_impl = _impl.data();
+
+ native_handle_type native_handle() const {return environ;}
+};
+
+template<>
+class native_environment_impl<char>
+{
+public:
+ using char_type = char;
+ using pointer_type = const char_type*;
+ using string_type = std::basic_string<char_type>;
+ using native_handle_type = char_type **;
+
+ void reload() {this->_env_impl = ::environ;}
+
+ string_type get(const pointer_type id) { return getenv(id); }
+ void set(const pointer_type id, const pointer_type value)
+ {
+ auto res = ::setenv(id, value, 1);
+ if (res != 0)
+ boost::process::detail::throw_last_error();
+ reload();
+ }
+ void reset(const pointer_type id)
+ {
+ auto res = ::unsetenv(id);
+ if (res != 0)
+ boost::process::detail::throw_last_error();
+ reload();
+ }
+
+ string_type get(const string_type & id) {return get(id.c_str());}
+ void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
+ void reset(const string_type & id) {reset(id.c_str());}
+
+ native_environment_impl() = default;
+ native_environment_impl(const native_environment_impl& ) = delete;
+ native_environment_impl(native_environment_impl && ) = default;
+ native_environment_impl & operator=(const native_environment_impl& ) = delete;
+ native_environment_impl & operator=(native_environment_impl && ) = default;
+ native_handle_type _env_impl = environ;
+
+ native_handle_type native_handle() const {return ::environ;}
+};
+
+
+
+template<typename Char>
+struct basic_environment_impl
+{
+ std::vector<std::basic_string<Char>> _data {};
+ static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & data);
+ std::vector<Char*> _env_arr{_load_var(_data)};
+public:
+ using char_type = Char;
+ using pointer_type = const char_type*;
+ using string_type = std::basic_string<char_type>;
+ using native_handle_type = Char**;
+ void reload()
+ {
+ _env_arr = _load_var(_data);
+ _env_impl = _env_arr.data();
+ }
+
+ string_type get(const pointer_type id) {return get(string_type(id));}
+ void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
+ void reset(const pointer_type id) {reset(string_type(id));}
+
+ string_type get(const string_type & id);
+ void set(const string_type & id, const string_type & value);
+ void reset(const string_type & id);
+
+ basic_environment_impl(const native_environment_impl<Char> & nei);
+ basic_environment_impl() = default;
+ basic_environment_impl(const basic_environment_impl& rhs)
+ : _data(rhs._data)
+ {
+
+ }
+ basic_environment_impl(basic_environment_impl && ) = default;
+ basic_environment_impl & operator=(const basic_environment_impl& rhs)
+ {
+ _data = rhs._data;
+ _env_arr = _load_var(_data);
+ _env_impl = &*_env_arr.begin();
+ return *this;
+ }
+ basic_environment_impl & operator=(basic_environment_impl && ) = default;
+
+ template<typename CharR>
+ explicit inline basic_environment_impl(
+ const basic_environment_impl<CharR>& rhs,
+ const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
+ : _data(rhs._data.size())
+ {
+ std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(),
+ [&](const std::basic_string<CharR> & st)
+ {
+ return ::boost::process::detail::convert(st, cv);
+ }
+
+ );
+ reload();
+ }
+
+ template<typename CharR>
+ basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
+ {
+ _data = ::boost::process::detail::convert(rhs._data);
+ _env_arr = _load_var(&*_data.begin());
+ _env_impl = &*_env_arr.begin();
+ return *this;
+ }
+
+ Char ** _env_impl = &*_env_arr.data();
+
+ native_handle_type native_handle() const {return &_data.front();}
+};
+
+
+template<typename Char>
+basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
+{
+ auto beg = nei.native_handle();
+
+ auto end = beg;
+ while (*end != nullptr)
+ end++;
+ this->_data.assign(beg, end);
+ reload();
+}
+
+
+template<typename Char>
+inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
+{
+ auto itr = std::find_if(_data.begin(), _data.end(),
+ [&](const string_type & st)
+ {
+ if (st.size() <= id.size())
+ return false;
+ return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
+ }
+ );
+
+ if (itr == _data.end())
+ {
+ return "";
+ }
+ else return
+ itr->data() + id.size(); //id=Thingy -> +2 points to T
+}
+
+template<typename Char>
+inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
+{
+ auto itr = std::find_if(_data.begin(), _data.end(),
+ [&](const string_type & st)
+ {
+ if (st.size() <= id.size())
+ return false;
+ return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
+ }
+ );
+
+ if (itr != _data.end())
+ *itr = id + equal_sign<Char>() + value;
+ else
+ _data.push_back(id + equal_sign<Char>() + value);
+
+ reload();
+}
+
+template<typename Char>
+inline void basic_environment_impl<Char>::reset(const string_type &id)
+{
+ auto itr = std::find_if(_data.begin(), _data.end(),
+ [&](const string_type & st)
+ {
+ if (st.size() <= id.size())
+ return false;
+ return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
+ }
+ );
+ if (itr != _data.end())
+ {
+ _data.erase(itr);//and remove it
+ }
+
+ reload();
+
+
+}
+
+template<typename Char>
+std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data)
+{
+ std::vector<Char*> ret;
+ ret.reserve(data.size() +1);
+
+ for (auto & val : data)
+ ret.push_back(&val.front());
+
+ ret.push_back(nullptr);
+ return ret;
+}
+
+template<typename T> constexpr T env_seperator();
+template<> constexpr char env_seperator() {return ':'; }
+template<> constexpr wchar_t env_seperator() {return L':'; }
+
+
+typedef int native_handle_t;
+
+inline int get_id() {return getpid(); }
+inline int native_handle() {return getpid(); }
+
+}
+
+}
+}
+}
+
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */
diff --git a/boost/process/detail/posix/exe.hpp b/boost/process/detail/posix/exe.hpp
new file mode 100644
index 0000000000..9de68acc4e
--- /dev/null
+++ b/boost/process/detail/posix/exe.hpp
@@ -0,0 +1,36 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_EXE_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_EXE_HPP_
+
+
+namespace boost
+{
+namespace process
+{
+namespace detail
+{
+namespace posix
+{
+
+template<class StringType, class Executor>
+inline void apply_exe(const StringType & exe, Executor & e)
+{
+ e.exe = exe.c_str();
+}
+
+}
+
+
+
+}
+}
+}
+
+
+
+#endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ARGS_HPP_ */
diff --git a/boost/process/detail/posix/executor.hpp b/boost/process/detail/posix/executor.hpp
new file mode 100644
index 0000000000..5d03fd184e
--- /dev/null
+++ b/boost/process/detail/posix/executor.hpp
@@ -0,0 +1,547 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_EXECUTOR_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_EXECUTOR_HPP
+
+#include <boost/process/detail/child_decl.hpp>
+#include <boost/process/error.hpp>
+#include <boost/process/pipe.hpp>
+#include <boost/process/detail/posix/basic_pipe.hpp>
+#include <boost/process/detail/posix/use_vfork.hpp>
+#include <boost/fusion/algorithm/iteration/for_each.hpp>
+#include <cstdlib>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#if !defined(__GLIBC__)
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#endif
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+inline int execvpe(const char* filename, char * const arg_list[], char* env[])
+{
+#if defined(__GLIBC__)
+ return ::execvpe(filename, arg_list, env);
+#else
+ //use my own implementation
+ std::string fn = filename;
+ if ((fn.find('/') == std::string::npos) && ::access(fn.c_str(), X_OK))
+ {
+ auto e = ::environ;
+ while ((*e != nullptr) && !boost::starts_with(*e, "PATH="))
+ e++;
+
+ if (e != nullptr)
+ {
+ std::vector<std::string> path;
+ boost::split(path, *e, boost::is_any_of(":"));
+
+ for (const std::string & pp : path)
+ {
+ auto p = pp + "/" + filename;
+ if (!::access(p.c_str(), X_OK))
+ {
+ fn = p;
+ break;
+ }
+ }
+ }
+ }
+ return ::execve(fn.c_str(), arg_list, env);
+#endif
+}
+
+template<typename Executor>
+struct on_setup_t
+{
+ Executor & exec;
+ on_setup_t(Executor & exec) : exec(exec) {};
+ template<typename T>
+ void operator()(T & t) const
+ {
+ if (!exec.error())
+ t.on_setup(exec);
+ }
+};
+
+template<typename Executor>
+struct on_error_t
+{
+ Executor & exec;
+ const std::error_code & error;
+ on_error_t(Executor & exec, const std::error_code & error) : exec(exec), error(error) {};
+ template<typename T>
+ void operator()(T & t) const
+ {
+ t.on_error(exec, error);
+ }
+};
+
+template<typename Executor>
+struct on_success_t
+{
+ Executor & exec;
+ on_success_t(Executor & exec) : exec(exec) {};
+ template<typename T>
+ void operator()(T & t) const {t.on_success(exec);}
+};
+
+
+
+template<typename Executor>
+struct on_fork_error_t
+{
+ Executor & exec;
+ const std::error_code & error;
+ on_fork_error_t(Executor & exec, const std::error_code & error) : exec(exec), error(error) {};
+
+ template<typename T>
+ void operator()(T & t) const
+ {
+ t.on_fork_error(exec, error);
+ }
+};
+
+
+template<typename Executor>
+struct on_exec_setup_t
+{
+ Executor & exec;
+ on_exec_setup_t(Executor & exec) : exec(exec) {};
+
+ template<typename T>
+ void operator()(T & t) const
+ {
+ t.on_exec_setup(exec);
+ }
+};
+
+
+template<typename Executor>
+struct on_exec_error_t
+{
+ Executor & exec;
+ const std::error_code &ec;
+ on_exec_error_t(Executor & exec, const std::error_code & error) : exec(exec), ec(error) {};
+
+ template<typename T>
+ void operator()(T & t) const
+ {
+ t.on_exec_error(exec, ec);
+ }
+};
+
+template<typename Executor>
+struct on_fork_success_t
+{
+ Executor & exec;
+ on_fork_success_t(Executor & exec) : exec(exec) {};
+
+ template<typename T>
+ void operator()(T & t) const
+ {
+ t.on_fork_success(exec);
+ }
+};
+
+template<typename Executor> on_setup_t <Executor> call_on_setup (Executor & exec) {return exec;}
+template<typename Executor> on_error_t <Executor> call_on_error (Executor & exec, const std::error_code & ec)
+{
+ return on_error_t<Executor> (exec, ec);
+}
+template<typename Executor> on_success_t<Executor> call_on_success(Executor & exec) {return exec;}
+
+template<typename Executor> on_fork_error_t <Executor> call_on_fork_error (Executor & exec, const std::error_code & ec)
+{
+ return on_fork_error_t<Executor> (exec, ec);
+}
+
+
+template<typename Executor> on_exec_setup_t <Executor> call_on_exec_setup (Executor & exec) {return exec;}
+template<typename Executor> on_exec_error_t <Executor> call_on_exec_error (Executor & exec, const std::error_code & ec)
+{
+ return on_exec_error_t<Executor> (exec, ec);
+}
+
+
+template<typename Sequence>
+class executor
+{
+ template<typename HasHandler, typename UseVFork>
+ void internal_error_handle(const std::error_code &ec, const char* msg, HasHandler, boost::mpl::true_, UseVFork) {}
+
+ int _pipe_sink = -1;
+
+ void write_error(const std::error_code & ec, const char * msg)
+ {
+ //I am the child
+ int len = ec.value();
+ ::write(_pipe_sink, &len, sizeof(int));
+
+ len = std::strlen(msg) + 1;
+ ::write(_pipe_sink, &len, sizeof(int));
+ ::write(_pipe_sink, msg, len);
+ }
+
+ void internal_error_handle(const std::error_code &ec, const char* msg, boost::mpl::true_ , boost::mpl::false_, boost::mpl::false_)
+ {
+ if (this->pid == 0) //on the fork.
+ write_error(ec, msg);
+ else
+ {
+ this->_ec = ec;
+ this->_msg = msg;
+ }
+ }
+ void internal_error_handle(const std::error_code &ec, const char* msg, boost::mpl::false_, boost::mpl::false_, boost::mpl::false_)
+ {
+ if (this->pid == 0)
+ write_error(ec, msg);
+ else
+ throw process_error(ec, msg);
+ }
+
+
+ void internal_error_handle(const std::error_code &ec, const char* msg, boost::mpl::true_ , boost::mpl::false_, boost::mpl::true_)
+ {
+ this->_ec = ec;
+ this->_msg = msg;
+ }
+ void internal_error_handle(const std::error_code &ec, const char* msg, boost::mpl::false_, boost::mpl::false_, boost::mpl::true_)
+ {
+ if (this->pid == 0)
+ {
+ this->_ec = ec;
+ this->_msg = msg;
+ }
+ else
+ throw process_error(ec, msg);
+ }
+
+ void check_error(boost::mpl::true_) {};
+ void check_error(boost::mpl::false_)
+ {
+ throw process_error(_ec, _msg);
+ }
+
+ typedef typename ::boost::process::detail::has_error_handler<Sequence>::type has_error_handler;
+ typedef typename ::boost::process::detail::has_ignore_error <Sequence>::type has_ignore_error;
+ typedef typename ::boost::process::detail::posix::shall_use_vfork<Sequence>::type shall_use_vfork;
+
+ inline child invoke(boost::mpl::true_ , boost::mpl::true_ );
+ inline child invoke(boost::mpl::false_, boost::mpl::true_ );
+ inline child invoke(boost::mpl::true_ , boost::mpl::false_ );
+ inline child invoke(boost::mpl::false_, boost::mpl::false_ );
+ void _write_error(int sink)
+ {
+ int data[2] = {_ec.value(),static_cast<int>(_msg.size())};
+ while (::write(sink, &data[0], sizeof(int) *2) == -1)
+ {
+ auto err = errno;
+
+ if (err == EBADF)
+ return;
+ else if ((err != EINTR) && (err != EAGAIN))
+ break;
+ }
+ while (::write(sink, &_msg.front(), _msg.size()) == -1)
+ {
+ auto err = errno;
+
+ if (err == EBADF)
+ return;
+ else if ((err != EINTR) && (err != EAGAIN))
+ break;
+ }
+ }
+
+ void _read_error(int source)
+ {
+ int data[2];
+
+ _ec.clear();
+ int count = 0;
+ while ((count = ::read(source, &data[0], sizeof(int) *2 ) ) == -1)
+ {
+ //actually, this should block until it's read.
+ auto err = errno;
+ if ((err != EAGAIN ) && (err != EINTR))
+ set_error(std::error_code(err, std::system_category()), "Error read pipe");
+ }
+ if (count == 0)
+ return ;
+
+ std::error_code ec(data[0], std::system_category());
+ std::string msg(data[1], ' ');
+
+ while (::read(source, &msg.front(), msg.size() ) == -1)
+ {
+ //actually, this should block until it's read.
+ auto err = errno;
+ if ((err == EBADF) || (err == EPERM))//that should occur on success, therefore return.
+ return;
+ //EAGAIN not yet forked, EINTR interrupted, i.e. try again
+ else if ((err != EAGAIN ) && (err != EINTR))
+ set_error(std::error_code(err, std::system_category()), "Error read pipe");
+ }
+ set_error(ec, std::move(msg));
+ }
+
+
+ std::error_code _ec;
+ std::string _msg;
+public:
+ executor(Sequence & seq) : seq(seq)
+ {
+ }
+
+ child operator()()
+ {
+ return invoke(has_ignore_error(), shall_use_vfork());
+ }
+
+
+ Sequence & seq;
+ const char * exe = nullptr;
+ char *const* cmd_line = nullptr;
+ bool cmd_style = false;
+ char **env = ::environ;
+ pid_t pid = -1;
+ std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active);
+
+ const std::error_code & error() const {return _ec;}
+
+ void set_error(const std::error_code &ec, const char* msg)
+ {
+ internal_error_handle(ec, msg, has_error_handler(), has_ignore_error(), shall_use_vfork());
+ }
+ void set_error(const std::error_code &ec, const std::string &msg) {set_error(ec, msg.c_str());};
+
+};
+
+template<typename Sequence>
+child executor<Sequence>::invoke(boost::mpl::true_, boost::mpl::false_) //ignore errors
+{
+ boost::fusion::for_each(seq, call_on_setup(*this));
+ if (_ec)
+ return child();
+
+ this->pid = ::fork();
+ if (pid == -1)
+ {
+ auto ec = boost::process::detail::get_last_error();
+ boost::fusion::for_each(seq, call_on_fork_error(*this, ec));
+ return child();
+ }
+ else if (pid == 0)
+ {
+ boost::fusion::for_each(seq, call_on_exec_setup(*this));
+ if (cmd_style)
+ ::boost::process::detail::posix::execvpe(exe, cmd_line, env);
+ else
+ ::execve(exe, cmd_line, env);
+ auto ec = boost::process::detail::get_last_error();
+ boost::fusion::for_each(seq, call_on_exec_error(*this, ec));
+ _exit(EXIT_FAILURE);
+ }
+
+ child c(child_handle(pid), exit_status);
+
+ boost::fusion::for_each(seq, call_on_success(*this));
+
+ return c;
+}
+
+template<typename Sequence>
+child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::false_)
+{
+ int p[2];
+ if (::pipe(p) == -1)
+ {
+ set_error(::boost::process::detail::get_last_error(), "pipe(2) failed");
+ return child();
+ }
+ if (::fcntl(p[1], F_SETFD, FD_CLOEXEC) == -1)
+ {
+ set_error(::boost::process::detail::get_last_error(), "fcntl(2) failed");
+ return child();
+ }
+ _ec.clear();
+ boost::fusion::for_each(seq, call_on_setup(*this));
+
+ if (_ec)
+ {
+ boost::fusion::for_each(seq, call_on_error(*this, _ec));
+ return child();
+ }
+
+ this->pid = ::fork();
+ if (pid == -1)
+ {
+ _ec = boost::process::detail::get_last_error();
+ _msg = "fork() failed";
+ boost::fusion::for_each(seq, call_on_fork_error(*this, _ec));
+ boost::fusion::for_each(seq, call_on_error(*this, _ec));
+
+ return child();
+ }
+ else if (pid == 0)
+ {
+ _pipe_sink = p[1];
+ ::close(p[0]);
+
+ boost::fusion::for_each(seq, call_on_exec_setup(*this));
+ if (cmd_style)
+ ::boost::process::detail::posix::execvpe(exe, cmd_line, env);
+ else
+ ::execve(exe, cmd_line, env);
+ _ec = boost::process::detail::get_last_error();
+ _msg = "execve failed";
+ boost::fusion::for_each(seq, call_on_exec_error(*this, _ec));
+
+ _write_error(p[1]);
+
+ _exit(EXIT_FAILURE);
+ return child();
+ }
+
+ child c(child_handle(pid), exit_status);
+
+
+
+ ::close(p[1]);
+ _read_error(p[0]);
+ ::close(p[0]);
+
+ if (_ec)
+ {
+ boost::fusion::for_each(seq, call_on_error(*this, _ec));
+ return child();
+ }
+ else
+ boost::fusion::for_each(seq, call_on_success(*this));
+
+ if (_ec)
+ {
+ boost::fusion::for_each(seq, call_on_error(*this, _ec));
+ return child();
+ }
+
+ return c;
+}
+
+#if BOOST_POSIX_HAS_VFORK
+
+
+template<typename Sequence>
+child executor<Sequence>::invoke(boost::mpl::true_, boost::mpl::true_) //ignore errors
+{
+ boost::fusion::for_each(seq, call_on_setup(*this));
+ if (_ec)
+ return child();
+ this->pid = ::vfork();
+ if (pid == -1)
+ {
+ auto ec = boost::process::detail::get_last_error();
+ boost::fusion::for_each(seq, call_on_fork_error(*this, ec));
+ return child();
+ }
+ else if (pid == 0)
+ {
+ boost::fusion::for_each(seq, call_on_exec_setup(*this));
+ ::execve(exe, cmd_line, env);
+ auto ec = boost::process::detail::get_last_error();
+ boost::fusion::for_each(seq, call_on_exec_error(*this, ec));
+ _exit(EXIT_FAILURE);
+ }
+ child c(child_handle(pid), exit_status);
+
+ boost::fusion::for_each(seq, call_on_success(*this));
+
+ return c;
+}
+
+template<typename Sequence>
+child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::true_)
+{
+ boost::fusion::for_each(seq, call_on_setup(*this));
+
+ if (_ec)
+ {
+ boost::fusion::for_each(seq, call_on_error(*this, _ec));
+ return child();
+ }
+ _ec.clear();
+
+ this->pid = ::vfork();
+ if (pid == -1)
+ {
+ _ec = boost::process::detail::get_last_error();
+ _msg = "fork() failed";
+ boost::fusion::for_each(seq, call_on_fork_error(*this, _ec));
+ boost::fusion::for_each(seq, call_on_error(*this, _ec));
+
+ return child();
+ }
+ else if (pid == 0)
+ {
+ boost::fusion::for_each(seq, call_on_exec_setup(*this));
+
+ if (cmd_style)
+ ::boost::process::detail::posix::execvpe(exe, cmd_line, env);
+ else
+ ::execve(exe, cmd_line, env);
+
+ _ec = boost::process::detail::get_last_error();
+ _msg = "execve failed";
+ boost::fusion::for_each(seq, call_on_exec_error(*this, _ec));
+
+ _exit(EXIT_FAILURE);
+ return child();
+ }
+ child c(child_handle(pid), exit_status);
+
+ check_error(has_error_handler());
+
+
+
+ if (_ec)
+ {
+ boost::fusion::for_each(seq, call_on_error(*this, _ec));
+ return child();
+ }
+ else
+ boost::fusion::for_each(seq, call_on_success(*this));
+
+ if (_ec)
+ {
+ boost::fusion::for_each(seq, call_on_error(*this, _ec));
+ return child();
+ }
+
+ return c;
+}
+
+#endif
+
+template<typename Char, typename Tup>
+inline executor<Tup> make_executor(Tup & tup)
+{
+ return executor<Tup>(tup);
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/fd.hpp b/boost/process/detail/posix/fd.hpp
new file mode 100644
index 0000000000..51790c3237
--- /dev/null
+++ b/boost/process/detail/posix/fd.hpp
@@ -0,0 +1,92 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_FD_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_FD_HPP
+
+#include <boost/process/detail/posix/handler.hpp>
+#include <unistd.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+
+struct close_fd_ : handler_base_ext
+{
+ close_fd_(int fd) : fd_(fd) {}
+
+ template <class PosixExecutor>
+ void on_exec_setup(PosixExecutor& e) const
+ {
+ if (::close(fd_) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "close() failed");
+ }
+
+private:
+ int fd_;
+};
+
+template <class Range>
+struct close_fds_ : handler_base_ext
+{
+public:
+ close_fds_(const Range &fds) : fds_(fds) {}
+
+ template <class PosixExecutor>
+ void on_exec_setup(PosixExecutor& e) const
+ {
+ for (auto & fd_ : fds_)
+ if (::close(fd_) == -1)
+ {
+ e.set_error(::boost::process::detail::get_last_error(), "close() failed");
+ break;
+ }
+ }
+
+private:
+ Range fds_;
+};
+
+
+
+template <class FileDescriptor>
+struct bind_fd_ : handler_base_ext
+{
+public:
+ bind_fd_(int id, const FileDescriptor &fd) : id_(id), fd_(fd) {}
+
+ template <class PosixExecutor>
+ void on_exec_setup(PosixExecutor& e) const
+ {
+ if (::dup2(fd_, id_) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+ }
+
+private:
+ int id_;
+ FileDescriptor fd_;
+};
+
+
+struct fd_
+{
+ constexpr fd_() {};
+ close_fd_ close(int _fd) const {return close_fd_(_fd);}
+ close_fds_<std::vector<int>> close(const std::initializer_list<int> & vec) const {return std::vector<int>(vec);}
+ template<typename Range>
+ close_fds_<Range> close(const Range & r) const {return r;}
+
+ template <class FileDescriptor>
+ bind_fd_<FileDescriptor> bind(int id, const FileDescriptor & fd) const {return {id, fd};}
+
+};
+
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/file_descriptor.hpp b/boost/process/detail/posix/file_descriptor.hpp
new file mode 100644
index 0000000000..72552444b0
--- /dev/null
+++ b/boost/process/detail/posix/file_descriptor.hpp
@@ -0,0 +1,76 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_FILE_DESCRIPTOR_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_FILE_DESCRIPTOR_HPP_
+
+#include <fcntl.h>
+#include <string>
+#include <boost/filesystem/path.hpp>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+struct file_descriptor
+{
+ enum mode_t
+ {
+ read = 1,
+ write = 2,
+ read_write = 3
+ };
+
+
+ file_descriptor() = default;
+ explicit file_descriptor(const boost::filesystem::path& p, mode_t mode = read_write)
+ : file_descriptor(p.native(), mode)
+ {
+ }
+
+ explicit file_descriptor(const std::string & path , mode_t mode = read_write)
+ : file_descriptor(path.c_str(), mode) {}
+
+
+ explicit file_descriptor(const char* path, mode_t mode = read_write)
+ : _handle(create_file(path, mode))
+ {
+
+ }
+
+ file_descriptor(const file_descriptor & ) = delete;
+ file_descriptor(file_descriptor && ) = default;
+
+ file_descriptor& operator=(const file_descriptor & ) = delete;
+ file_descriptor& operator=(file_descriptor && ) = default;
+
+ ~file_descriptor()
+ {
+ if (_handle != -1)
+ ::close(_handle);
+ }
+
+ int handle() const { return _handle;}
+
+private:
+ static int create_file(const char* name, mode_t mode )
+ {
+ switch(mode)
+ {
+ case read:
+ return ::open(name, O_RDONLY);
+ case write:
+ return ::open(name, O_WRONLY | O_CREAT, 0660);
+ case read_write:
+ return ::open(name, O_RDWR | O_CREAT, 0660);
+ default:
+ return -1;
+ }
+ }
+
+ int _handle = -1;
+};
+
+}}}}
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_ */
diff --git a/boost/process/detail/posix/file_in.hpp b/boost/process/detail/posix/file_in.hpp
new file mode 100644
index 0000000000..c3ceeeead2
--- /dev/null
+++ b/boost/process/detail/posix/file_in.hpp
@@ -0,0 +1,40 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_FILE_IN_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_FILE_IN_HPP
+
+#include <boost/process/pipe.hpp>
+#include <boost/process/detail/posix/handler.hpp>
+#include <boost/process/detail/posix/file_descriptor.hpp>
+#include <cstdio>
+#include <unistd.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+struct file_in : handler_base_ext
+{
+ file_descriptor file;
+ int handle = file.handle();
+
+ template<typename T>
+ file_in(T&& t) : file(std::forward<T>(t)) {}
+ file_in(FILE * f) : handle(fileno(f)) {}
+
+ template <class WindowsExecutor>
+ void on_exec_setup(WindowsExecutor &e) const
+ {
+ if (::dup2(handle, STDIN_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+ }
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/file_out.hpp b/boost/process/detail/posix/file_out.hpp
new file mode 100644
index 0000000000..6fef732598
--- /dev/null
+++ b/boost/process/detail/posix/file_out.hpp
@@ -0,0 +1,65 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_POSIX_FILE_OUT_HPP
+#define BOOST_PROCESS_POSIX_FILE_OUT_HPP
+
+#include <boost/process/detail/posix/handler.hpp>
+#include <boost/process/detail/posix/file_descriptor.hpp>
+
+#include <unistd.h>
+namespace boost { namespace process { namespace detail { namespace posix {
+
+template<int p1, int p2>
+struct file_out : handler_base_ext
+{
+ file_descriptor file;
+ int handle = file.handle();
+
+ template<typename T>
+ file_out(T&& t) : file(std::forward<T>(t), file_descriptor::write), handle(file.handle()) {}
+ file_out(FILE * f) : handle(fileno(f)) {}
+
+
+ template <typename Executor>
+ void on_exec_setup(Executor &e) const;
+};
+
+template<>
+template<typename Executor>
+void file_out<1,-1>::on_exec_setup(Executor &e) const
+{
+ if (::dup2(handle, STDOUT_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+}
+
+template<>
+template<typename Executor>
+void file_out<2,-1>::on_exec_setup(Executor &e) const
+{
+ if (::dup2(handle, STDERR_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+}
+
+template<>
+template<typename Executor>
+void file_out<1,2>::on_exec_setup(Executor &e) const
+{
+ if (::dup2(handle, STDOUT_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+
+ if (::dup2(handle, STDERR_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/group_handle.hpp b/boost/process/detail/posix/group_handle.hpp
new file mode 100644
index 0000000000..856b36a6b0
--- /dev/null
+++ b/boost/process/detail/posix/group_handle.hpp
@@ -0,0 +1,103 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_GROUP_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_GROUP_HPP_
+
+#include <boost/process/detail/posix/child_handle.hpp>
+#include <system_error>
+#include <unistd.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+
+
+struct group_handle
+{
+ pid_t grp = -1;
+
+ typedef pid_t handle_t;
+ handle_t handle() const { return grp; }
+
+ explicit group_handle(handle_t h) :
+ grp(h)
+ {
+ }
+
+
+ group_handle() = default;
+
+ ~group_handle() = default;
+ group_handle(const group_handle & c) = delete;
+ group_handle(group_handle && c) : grp(c.grp)
+ {
+ c.grp = -1;
+ }
+ group_handle &operator=(const group_handle & c) = delete;
+ group_handle &operator=(group_handle && c)
+ {
+
+ grp = c.grp;
+ c.grp = -1;
+ return *this;
+ }
+
+ void add(handle_t proc)
+ {
+ if (::setpgid(proc, grp))
+ throw_last_error();
+ }
+ void add(handle_t proc, std::error_code & ec) noexcept
+ {
+ if (::setpgid(proc, grp))
+ ec = get_last_error();
+ }
+
+ bool has(handle_t proc)
+ {
+ return ::getpgid(proc) == grp;
+ }
+ bool has(handle_t proc, std::error_code & ec) noexcept
+ {
+ return ::getpgid(proc) == grp;
+
+ }
+
+ bool valid() const
+ {
+ return grp != -1;
+ }
+
+};
+
+inline void terminate(group_handle &p)
+{
+ if (::killpg(p.grp, SIGKILL) == -1)
+ boost::process::detail::throw_last_error("killpg(2) failed");
+ p.grp = -1;
+}
+
+inline void terminate(group_handle &p, std::error_code &ec) noexcept
+{
+ if (::killpg(p.grp, SIGKILL) == -1)
+ ec = boost::process::detail::get_last_error();
+ else
+ ec.clear();
+
+ p.grp = -1;
+}
+
+
+inline bool in_group()
+{
+ return true;
+}
+
+
+
+}}}}
+
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_ */
diff --git a/boost/process/detail/posix/group_ref.hpp b/boost/process/detail/posix/group_ref.hpp
new file mode 100644
index 0000000000..d46e631fe7
--- /dev/null
+++ b/boost/process/detail/posix/group_ref.hpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_GROUP_REF_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_GROUP_REF_HPP_
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/posix/group_handle.hpp>
+#include <boost/process/detail/posix/handler.hpp>
+#include <unistd.h>
+
+
+namespace boost { namespace process {
+
+namespace detail { namespace posix {
+
+
+
+struct group_ref : handler_base_ext
+{
+ group_handle & grp;
+
+
+ explicit group_ref(group_handle & g) :
+ grp(g)
+ {}
+
+ template <class Executor>
+ void on_exec_setup(Executor& exec) const
+ {
+ if (grp.grp == -1)
+ ::setpgid(0, 0);
+ else
+ ::setpgid(0, grp.grp);
+ }
+
+ template <class Executor>
+ void on_success(Executor& exec) const
+ {
+ if (grp.grp == -1)
+ grp.grp = exec.pid;
+
+ }
+
+};
+
+}}}}
+
+
+#endif /* BOOST_PROCESS_DETAIL_POSIX_GROUP_REF_HPP_ */
diff --git a/boost/process/detail/posix/handler.hpp b/boost/process/detail/posix/handler.hpp
new file mode 100644
index 0000000000..506db4e649
--- /dev/null
+++ b/boost/process/detail/posix/handler.hpp
@@ -0,0 +1,74 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_
+
+#include <boost/process/detail/handler_base.hpp>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+//does not extend anything.
+struct handler_base_ext : handler_base
+{
+ template<typename Executor>
+ void on_fork_error (Executor &, const std::error_code&) const {}
+
+ template<typename Executor>
+ void on_exec_setup (Executor &) const {}
+
+ template<typename Executor>
+ void on_exec_error (Executor &, const std::error_code&) const {}
+};
+
+
+template <class Handler>
+struct on_fork_error_ : handler_base_ext
+{
+ explicit on_fork_error_(Handler handler) : handler_(handler) {}
+
+ template <class Executor>
+ void on_fork_error(Executor &e, const std::error_code &ec) const
+ {
+ handler_(e, ec);
+ }
+private:
+ Handler handler_;
+};
+
+
+template <class Handler>
+struct on_exec_setup_ : handler_base_ext
+{
+ explicit on_exec_setup_(Handler handler) : handler_(handler) {}
+
+ template <class Executor>
+ void on_exec_setup(Executor &e) const
+ {
+ handler_(e);
+ }
+private:
+ Handler handler_;
+};
+
+template <class Handler>
+struct on_exec_error_ : handler_base_ext
+{
+ explicit on_exec_error_(Handler handler) : handler_(handler) {}
+
+ template <class Executor>
+ void on_exec_error(Executor &e, const std::error_code &ec) const
+ {
+ handler_(e, ec);
+ }
+private:
+ Handler handler_;
+};
+
+}}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_ */
diff --git a/boost/process/detail/posix/io_service_ref.hpp b/boost/process/detail/posix/io_service_ref.hpp
new file mode 100644
index 0000000000..ced1d51033
--- /dev/null
+++ b/boost/process/detail/posix/io_service_ref.hpp
@@ -0,0 +1,155 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_POSIX_IO_SERVICE_REF_HPP_
+#define BOOST_PROCESS_POSIX_IO_SERVICE_REF_HPP_
+
+#include <boost/process/detail/posix/handler.hpp>
+#include <boost/process/detail/posix/async_handler.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/signal_set.hpp>
+
+#include <boost/fusion/algorithm/iteration/for_each.hpp>
+#include <boost/fusion/algorithm/transformation/filter_if.hpp>
+#include <boost/fusion/algorithm/transformation/transform.hpp>
+#include <boost/fusion/view/transform_view.hpp>
+#include <boost/fusion/container/vector/convert.hpp>
+
+
+#include <functional>
+#include <type_traits>
+#include <memory>
+#include <vector>
+#include <sys/wait.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+template<typename Executor>
+struct on_exit_handler_transformer
+{
+ Executor & exec;
+ on_exit_handler_transformer(Executor & exec) : exec(exec) {}
+ template<typename Sig>
+ struct result;
+
+ template<typename T>
+ struct result<on_exit_handler_transformer<Executor>(T&)>
+ {
+ typedef typename T::on_exit_handler_t type;
+ };
+
+ template<typename T>
+ auto operator()(T& t) const -> typename T::on_exit_handler_t
+ {
+ return t.on_exit_handler(exec);
+ }
+};
+
+template<typename Executor>
+struct async_handler_collector
+{
+ Executor & exec;
+ std::vector<std::function<void(int, const std::error_code & ec)>> &handlers;
+
+
+ async_handler_collector(Executor & exec,
+ std::vector<std::function<void(int, const std::error_code & ec)>> &handlers)
+ : exec(exec), handlers(handlers) {}
+
+ template<typename T>
+ void operator()(T & t) const
+ {
+ handlers.push_back(t.on_exit_handler(exec));
+ };
+};
+
+//Also set's up waiting for the exit, so it can close async stuff.
+struct io_service_ref : handler_base_ext
+{
+ io_service_ref(boost::asio::io_service & ios) : ios(ios)
+ {
+
+ }
+ boost::asio::io_service &get() {return ios;};
+
+ boost::asio::signal_set *signal_p = nullptr;
+
+ template <class Executor>
+ void on_setup(Executor& exec)
+ {
+ //must be on the heap so I can move it into the lambda.
+ auto asyncs = boost::fusion::filter_if<
+ is_async_handler<
+ typename std::remove_reference< boost::mpl::_ > ::type
+ >>(exec.seq);
+
+ //ok, check if there are actually any.
+ if (boost::fusion::empty(asyncs))
+ return;
+
+ std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
+ funcs.reserve(boost::fusion::size(asyncs));
+ boost::fusion::for_each(asyncs, async_handler_collector<Executor>(exec, funcs));
+
+ wait_handler wh(std::move(funcs), ios, exec.exit_status);
+
+ signal_p = wh.signal_.get();
+ signal_p->async_wait(std::move(wh));
+
+ }
+
+ template <class Executor>
+ void on_error(Executor & exec, const std::error_code & ec) const
+ {
+ if (signal_p != nullptr)
+ {
+ boost::system::error_code ec;
+ signal_p->cancel(ec);
+ }
+ }
+
+ struct wait_handler
+ {
+ std::shared_ptr<boost::asio::signal_set> signal_;
+ std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
+ std::shared_ptr<std::atomic<int>> exit_status;
+
+ wait_handler(const wait_handler & ) = default;
+ wait_handler(wait_handler && ) = default;
+ wait_handler(
+ std::vector<std::function<void(int, const std::error_code & ec)>> && funcs,
+ boost::asio::io_service & ios,
+ const std::shared_ptr<std::atomic<int>> &exit_status)
+ : signal_(new boost::asio::signal_set(ios, SIGCHLD)),
+ funcs(std::move(funcs)),
+ exit_status(exit_status)
+ {
+
+ }
+ void operator()(const boost::system::error_code & ec_in, int /*signal*/)
+ {
+ if (ec_in.value() == boost::asio::error::operation_aborted)
+ return;
+
+
+ int status;
+ ::wait(&status);
+
+ std::error_code ec(ec_in.value(), std::system_category());
+ int val = WEXITSTATUS(status);
+ exit_status->store(status);
+
+ for (auto & func : funcs)
+ func(val, ec);
+ }
+
+ };
+private:
+ boost::asio::io_service &ios;
+};
+
+}}}}
+
+#endif /* BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_ */
diff --git a/boost/process/detail/posix/is_running.hpp b/boost/process/detail/posix/is_running.hpp
new file mode 100644
index 0000000000..e8a009dd22
--- /dev/null
+++ b/boost/process/detail/posix/is_running.hpp
@@ -0,0 +1,78 @@
+// Copyright (c) 2106 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_IS_RUNNING_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_IS_RUNNING_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/posix/child_handle.hpp>
+#include <system_error>
+#include <sys/wait.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+
+constexpr int still_active = 0x7F;
+static_assert(!WIFEXITED(still_active), "Internal Error");
+
+inline bool is_running(const child_handle &p, int & exit_code)
+{
+ int status;
+ auto ret = ::waitpid(p.pid, &status, WNOHANG|WUNTRACED);
+
+ if (ret == -1)
+ {
+ if (errno != ECHILD) //because it no child is running, than this one isn't either, obviously.
+ ::boost::process::detail::throw_last_error("is_running error");
+
+ return false;
+ }
+ else if (ret == 0)
+ return true;
+ else //exited
+ {
+ if (WIFEXITED(status))
+ exit_code = status;
+ return false;
+ }
+}
+
+inline bool is_running(const child_handle &p, int & exit_code, std::error_code &ec) noexcept
+{
+ int status;
+ auto ret = ::waitpid(p.pid, &status, WNOHANG|WUNTRACED);
+
+ if (ret == -1)
+ {
+ if (errno != ECHILD) //because it no child is running, than this one isn't either, obviously.
+ ec = ::boost::process::detail::get_last_error();
+ return false;
+ }
+ else if (ret == 0)
+ return true;
+ else
+ {
+ ec.clear();
+
+ if (WIFEXITED(status))
+ exit_code = status;
+
+ return false;
+ }
+}
+
+inline bool is_running(int code)
+{
+ return !WIFEXITED(code);
+}
+
+inline int eval_exit_status(int code)
+{
+ return WEXITSTATUS(code);
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/null_in.hpp b/boost/process/detail/posix/null_in.hpp
new file mode 100644
index 0000000000..9f082054c6
--- /dev/null
+++ b/boost/process/detail/posix/null_in.hpp
@@ -0,0 +1,35 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_NULL_IN_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_NULL_IN_HPP
+
+#include <boost/process/pipe.hpp>
+#include <boost/process/detail/posix/handler.hpp>
+#include <boost/process/detail/posix/file_descriptor.hpp>
+#include <unistd.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+struct null_in : handler_base_ext
+{
+ file_descriptor source{"/dev/null", file_descriptor::read};
+
+public:
+ template <class Executor>
+ void on_exec_setup(Executor &e) const
+ {
+ if (::dup2(source.handle(), STDIN_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+ }
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/null_out.hpp b/boost/process/detail/posix/null_out.hpp
new file mode 100644
index 0000000000..ed4f915f35
--- /dev/null
+++ b/boost/process/detail/posix/null_out.hpp
@@ -0,0 +1,58 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_POSIX_PIPE_OUT_HPP
+#define BOOST_PROCESS_POSIX_PIPE_OUT_HPP
+
+#include <boost/process/detail/posix/handler.hpp>
+#include <boost/process/detail/posix/file_descriptor.hpp>
+
+#include <unistd.h>
+namespace boost { namespace process { namespace detail { namespace posix {
+
+template<int p1, int p2>
+struct null_out : handler_base_ext
+{
+ file_descriptor sink{"/dev/null", file_descriptor::write};
+
+ template <typename Executor>
+ void on_exec_setup(Executor &e) const;
+};
+
+template<>
+template<typename Executor>
+void null_out<1,-1>::on_exec_setup(Executor &e) const
+{
+ if (::dup2(sink.handle(), STDOUT_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+}
+
+template<>
+template<typename Executor>
+void null_out<2,-1>::on_exec_setup(Executor &e) const
+{
+ if (::dup2(sink.handle(), STDERR_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+}
+
+template<>
+template<typename Executor>
+void null_out<1,2>::on_exec_setup(Executor &e) const
+{
+ if (::dup2(sink.handle(), STDOUT_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+
+ if (::dup2(sink.handle(), STDERR_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/on_exit.hpp b/boost/process/detail/posix/on_exit.hpp
new file mode 100644
index 0000000000..d3160aff32
--- /dev/null
+++ b/boost/process/detail/posix/on_exit.hpp
@@ -0,0 +1,35 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_POSIX_ON_EXIT_HPP_
+#define BOOST_PROCESS_POSIX_ON_EXIT_HPP_
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/posix/async_handler.hpp>
+#include <system_error>
+#include <functional>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+struct on_exit_ : boost::process::detail::posix::async_handler
+{
+ std::function<void(int, const std::error_code&)> handler;
+ on_exit_(const std::function<void(int, const std::error_code&)> & handler) : handler(handler)
+ {
+
+ }
+
+ template<typename Executor>
+ std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec)
+ {
+ return handler;
+
+ };
+};
+
+
+}}}}
+#endif /* BOOST_PROCESS_POSIX_ON_EXIT_HPP_ */
diff --git a/boost/process/detail/posix/pipe_in.hpp b/boost/process/detail/posix/pipe_in.hpp
new file mode 100644
index 0000000000..fa294cf310
--- /dev/null
+++ b/boost/process/detail/posix/pipe_in.hpp
@@ -0,0 +1,90 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_POSIX_PIPE_IN_HPP
+#define BOOST_PROCESS_POSIX_PIPE_IN_HPP
+
+#include <boost/process/pipe.hpp>
+#include <boost/process/detail/posix/handler.hpp>
+#include <unistd.h>
+
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+struct pipe_in : handler_base_ext
+{
+ int source;
+ int sink; //opposite end
+
+ pipe_in(int sink, int source) : source(source), sink(sink) {}
+
+
+ template<typename T>
+ pipe_in(T & p) : source(p.native_source()), sink(p.native_sink())
+ {
+ p.assign_source(-1);
+ }
+
+ template<typename Executor>
+ void on_error(Executor &, const std::error_code &) const
+ {
+ ::close(source);
+ }
+
+ template<typename Executor>
+ void on_success(Executor &) const
+ {
+ ::close(source);
+ }
+
+ template <class Executor>
+ void on_exec_setup(Executor &e) const
+ {
+ if (::dup2(source, STDIN_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+ ::close(source);
+ ::close(sink);
+ }
+
+};
+
+class async_pipe;
+
+struct async_pipe_in : public pipe_in
+{
+ async_pipe &pipe;
+
+ template<typename AsyncPipe>
+ async_pipe_in(AsyncPipe & p) : pipe_in(p.native_sink(), p.native_source()), pipe(p)
+ {
+ }
+
+ template<typename Pipe, typename Executor>
+ static void close(Pipe & pipe, Executor &)
+ {
+ boost::system::error_code ec;
+ std::move(pipe).source().close(ec);
+ }
+
+ template<typename Executor>
+ void on_error(Executor & exec, const std::error_code &)
+ {
+ close(pipe, exec);
+ }
+
+ template<typename Executor>
+ void on_success(Executor &exec)
+ {
+ close(pipe, exec);
+ }
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/pipe_out.hpp b/boost/process/detail/posix/pipe_out.hpp
new file mode 100644
index 0000000000..0148c19d26
--- /dev/null
+++ b/boost/process/detail/posix/pipe_out.hpp
@@ -0,0 +1,116 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_PIPE_OUT_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_PIPE_OUT_HPP
+
+#include <boost/process/pipe.hpp>
+#include <boost/process/detail/posix/handler.hpp>
+#include <unistd.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+template<int p1, int p2>
+struct pipe_out : handler_base_ext
+{
+ int sink;
+ int source; //opposite end
+
+ pipe_out(int sink, int source) : sink(sink), source(source) {}
+
+ template<typename T>
+ pipe_out(T & p) : sink(p.native_sink()), source(p.native_source())
+ {
+ p.assign_sink(-1);
+ }
+
+ template<typename Executor>
+ void on_error(Executor &, const std::error_code &) const
+ {
+ ::close(sink);
+ }
+
+ template<typename Executor>
+ void on_success(Executor &) const
+ {
+ ::close(sink);
+ }
+
+ template <typename Executor>
+ void on_exec_setup(Executor &e) const;
+};
+
+template<>
+template<typename Executor>
+void pipe_out<1,-1>::on_exec_setup(Executor &e) const
+{
+ if (::dup2(sink, STDOUT_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup3() failed");
+ ::close(sink);
+ ::close(source);
+}
+
+template<>
+template<typename Executor>
+void pipe_out<2,-1>::on_exec_setup(Executor &e) const
+{
+ if (::dup2(sink, STDERR_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+ ::close(sink);
+ ::close(source);
+}
+
+template<>
+template<typename Executor>
+void pipe_out<1,2>::on_exec_setup(Executor &e) const
+{
+ if (::dup2(sink, STDOUT_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+ if (::dup2(sink, STDERR_FILENO) == -1)
+ e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+ ::close(sink);
+ ::close(source);
+}
+
+class async_pipe;
+
+template<int p1, int p2>
+struct async_pipe_out : public pipe_out<p1, p2>
+{
+ async_pipe &pipe;
+ template<typename AsyncPipe>
+ async_pipe_out(AsyncPipe & p) : pipe_out<p1, p2>(p.native_sink(), p.native_source()), pipe(p)
+ {
+ }
+
+ template<typename Pipe, typename Executor>
+ static void close(Pipe & pipe, Executor &)
+ {
+ boost::system::error_code ec;
+ std::move(pipe).sink().close(ec);
+ }
+
+ template<typename Executor>
+ void on_error(Executor & exec, const std::error_code &)
+ {
+ close(pipe, exec);
+ }
+
+ template<typename Executor>
+ void on_success(Executor &exec)
+ {
+ close(pipe, exec);
+ }
+};
+
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/search_path.hpp b/boost/process/detail/posix/search_path.hpp
new file mode 100644
index 0000000000..1ce5c65575
--- /dev/null
+++ b/boost/process/detail/posix/search_path.hpp
@@ -0,0 +1,39 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_POSIX_SEARCH_PATH_HPP
+#define BOOST_PROCESS_POSIX_SEARCH_PATH_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/tokenizer.hpp>
+#include <string>
+#include <stdexcept>
+#include <stdlib.h>
+#include <unistd.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+inline boost::filesystem::path search_path(
+ const boost::filesystem::path &filename,
+ const std::vector<boost::filesystem::path> &path)
+{
+ std::string result;
+ for (const boost::filesystem::path & pp : path)
+ {
+ auto p = pp / filename;
+ if (!::access(p.c_str(), X_OK))
+ return p;
+ }
+ return "";
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/shell_path.hpp b/boost/process/detail/posix/shell_path.hpp
new file mode 100644
index 0000000000..870cab6b90
--- /dev/null
+++ b/boost/process/detail/posix/shell_path.hpp
@@ -0,0 +1,32 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_POSIX_SHELL_PATH_HPP
+#define BOOST_PROCESS_POSIX_SHELL_PATH_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/filesystem/path.hpp>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+inline boost::filesystem::path shell_path()
+{
+ return "/bin/sh";
+}
+
+inline boost::filesystem::path shell_path(std::error_code &ec)
+{
+ ec.clear();
+ return "/bin/sh";
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/signal.hpp b/boost/process/detail/posix/signal.hpp
new file mode 100644
index 0000000000..f9ef32d05d
--- /dev/null
+++ b/boost/process/detail/posix/signal.hpp
@@ -0,0 +1,79 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_POSIX_SIGNAL_HPP
+#define BOOST_PROCESS_POSIX_SIGNAL_HPP
+
+#include <boost/process/detail/posix/handler.hpp>
+#include <signal.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+#if defined(__GLIBC__)
+ using sighandler_t = ::sighandler_t;
+#else
+ using sighandler_t = void(*)(int);
+#endif
+
+
+struct sig_init_ : handler_base_ext
+{
+
+ sig_init_ (sighandler_t handler) : _handler(handler) {}
+
+ template <class PosixExecutor>
+ void on_exec_setup(PosixExecutor&)
+ {
+ _old = ::signal(SIGCHLD, _handler);
+ }
+
+ template <class Executor>
+ void on_error(Executor&, const std::error_code &)
+ {
+ if (!_reset)
+ {
+ ::signal(SIGCHLD, _old);
+ _reset = true;
+ }
+ }
+
+ template <class Executor>
+ void on_success(Executor&)
+ {
+ if (!_reset)
+ {
+ ::signal(SIGCHLD, _old);
+ _reset = true;
+ }
+ }
+private:
+ bool _reset = false;
+ ::boost::process::detail::posix::sighandler_t _old{0};
+ ::boost::process::detail::posix::sighandler_t _handler{0};
+};
+
+struct sig_
+{
+ constexpr sig_() {}
+
+ sig_init_ operator()(::boost::process::detail::posix::sighandler_t h) const {return h;}
+ sig_init_ operator= (::boost::process::detail::posix::sighandler_t h) const {return h;}
+ sig_init_ dfl() const {return SIG_DFL;}
+ sig_init_ ign() const {return SIG_IGN;}
+
+};
+
+
+
+
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/start_dir.hpp b/boost/process/detail/posix/start_dir.hpp
new file mode 100644
index 0000000000..1b73172c8b
--- /dev/null
+++ b/boost/process/detail/posix/start_dir.hpp
@@ -0,0 +1,38 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_START_DIR_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_START_DIR_HPP
+
+#include <boost/process/detail/posix/handler.hpp>
+#include <string>
+#include <unistd.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+template<typename Char>
+struct start_dir_init : handler_base_ext
+{
+ typedef Char value_type;
+ typedef std::basic_string<value_type> string_type;
+ start_dir_init(const string_type &s) : s_(s) {}
+
+ template <class PosixExecutor>
+ void on_exec_setup(PosixExecutor&) const
+ {
+ ::chdir(s_.c_str());
+ }
+ const string_type & str() const {return s_;}
+private:
+ string_type s_;
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/terminate.hpp b/boost/process/detail/posix/terminate.hpp
new file mode 100644
index 0000000000..d8048362b0
--- /dev/null
+++ b/boost/process/detail/posix/terminate.hpp
@@ -0,0 +1,44 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_TERMINATE_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_TERMINATE_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/posix/child_handle.hpp>
+#include <system_error>
+#include <signal.h>
+#include <sys/wait.h>
+
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+
+inline void terminate(const child_handle &p)
+{
+ if (::kill(p.pid, SIGKILL) == -1)
+ boost::process::detail::throw_last_error("kill(2) failed");
+ int status;
+ ::waitpid(p.pid, &status, 0); //just to clean it up
+}
+
+inline void terminate(const child_handle &p, std::error_code &ec) noexcept
+{
+ if (::kill(p.pid, SIGKILL) == -1)
+ ec = boost::process::detail::get_last_error();
+ else
+ ec.clear();
+
+ int status;
+ ::waitpid(p.pid, &status, 0); //just to clean it up
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/use_vfork.hpp b/boost/process/detail/posix/use_vfork.hpp
new file mode 100644
index 0000000000..98f74b24ff
--- /dev/null
+++ b/boost/process/detail/posix/use_vfork.hpp
@@ -0,0 +1,33 @@
+/*
+ * use_vfork.hpp
+ *
+ * Created on: 17.06.2016
+ * Author: klemens
+ */
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_USE_VFORK_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_USE_VFORK_HPP_
+
+
+#include <boost/process/detail/posix/handler.hpp>
+#include <boost/fusion/sequence/intrinsic/has_key.hpp>
+#include <boost/fusion/container/set/convert.hpp>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+struct use_vfork_ : handler_base_ext
+{
+ constexpr use_vfork_(){};
+};
+
+template<typename Sequence>
+struct shall_use_vfork
+{
+ typedef typename boost::fusion::result_of::as_set<Sequence>::type set_type;
+ typedef typename boost::fusion::result_of::has_key<set_type, const use_vfork_&>::type type;
+};
+
+
+}}}}
+
+#endif /* BOOST_PROCESS_DETAIL_POSIX_USE_VFORK_HPP_ */
diff --git a/boost/process/detail/posix/wait_for_exit.hpp b/boost/process/detail/posix/wait_for_exit.hpp
new file mode 100644
index 0000000000..bf25e2a3d8
--- /dev/null
+++ b/boost/process/detail/posix/wait_for_exit.hpp
@@ -0,0 +1,205 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_WAIT_FOR_EXIT_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_WAIT_FOR_EXIT_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/posix/child_handle.hpp>
+#include <system_error>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+inline void wait(const child_handle &p, int & exit_code)
+{
+ pid_t ret;
+ int status;
+ do
+ {
+ ret = ::waitpid(p.pid, &status, 0);
+ } while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
+ if (ret == -1)
+ boost::process::detail::throw_last_error("waitpid(2) failed");
+ exit_code = status;
+}
+
+inline void wait(const child_handle &p, int & exit_code, std::error_code &ec) noexcept
+{
+ pid_t ret;
+ int status;
+
+ do
+ {
+ ret = ::waitpid(p.pid, &status, 0);
+ }
+ while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
+
+ if (ret == -1)
+ ec = boost::process::detail::get_last_error();
+ else
+ {
+ ec.clear();
+ exit_code = status;
+ }
+
+
+}
+
+template< class Rep, class Period >
+inline bool wait_for(
+ const child_handle &p,
+ int & exit_code,
+ const std::chrono::duration<Rep, Period>& rel_time)
+{
+
+ pid_t ret;
+ int status;
+
+ auto start = std::chrono::system_clock::now();
+ auto time_out = start + rel_time;
+
+ bool time_out_occured = false;
+ do
+ {
+ ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG);
+ if (std::chrono::system_clock::now() >= time_out)
+ {
+ time_out_occured = true;
+ break;
+ }
+ }
+ while (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status)));
+
+
+ if (ret == -1)
+ boost::process::detail::throw_last_error("waitpid(2) failed");
+
+ exit_code = status;
+
+ return !time_out_occured;
+}
+
+
+template< class Rep, class Period >
+inline bool wait_for(
+ const child_handle &p,
+ int & exit_code,
+ const std::chrono::duration<Rep, Period>& rel_time,
+ std::error_code & ec) noexcept
+{
+
+ pid_t ret;
+ int status;
+
+ auto start = std::chrono::system_clock::now();
+ auto time_out = start + rel_time;
+
+ bool time_out_occured = false;
+ do
+ {
+ ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG);
+ if (std::chrono::system_clock::now() >= time_out)
+ {
+ time_out_occured = true;
+ break;
+ }
+ }
+ while (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status)));
+
+
+ if (ret == -1)
+ ec = boost::process::detail::get_last_error();
+ else
+ {
+ ec.clear();
+ exit_code = status;
+ }
+
+ return !time_out_occured;
+}
+
+
+
+template< class Rep, class Period >
+inline bool wait_until(
+ const child_handle &p,
+ int & exit_code,
+ const std::chrono::duration<Rep, Period>& time_out)
+{
+
+ pid_t ret;
+ int status;
+
+ bool time_out_occured = false;
+ do
+ {
+ ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG);
+ if (std::chrono::system_clock::now() >= time_out)
+ {
+ time_out_occured = true;
+ break;
+ }
+ }
+ while (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status)));
+
+
+ if (ret == -1)
+ boost::process::detail::throw_last_error("waitpid(2) failed");
+
+ exit_code = status;
+
+ return !time_out_occured;
+}
+
+
+template< class Rep, class Period >
+inline bool wait_until(
+ const child_handle &p,
+ int & exit_code,
+ const std::chrono::duration<Rep, Period>& time_out,
+ std::error_code & ec) noexcept
+{
+
+ pid_t ret;
+ int status;
+
+ bool time_out_occured = false;
+ do
+ {
+ ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG);
+ if (std::chrono::system_clock::now() >= time_out)
+ {
+ time_out_occured = true;
+ break;
+ }
+ }
+ while (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status)));
+
+
+ if (ret == -1)
+ ec = boost::process::detail::get_last_error();
+ else
+ {
+ ec.clear();
+ exit_code = status;
+ }
+
+ return !time_out_occured;
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/posix/wait_group.hpp b/boost/process/detail/posix/wait_group.hpp
new file mode 100644
index 0000000000..8b768ffc14
--- /dev/null
+++ b/boost/process/detail/posix/wait_group.hpp
@@ -0,0 +1,191 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_WAIT_GROUP_HPP
+#define BOOST_PROCESS_DETAIL_POSIX_WAIT_GROUP_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/posix/group_handle.hpp>
+#include <system_error>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+inline void wait(const group_handle &p)
+{
+ pid_t ret;
+ int status;
+ do
+ {
+ ret = ::waitpid(-p.grp, &status, 0);
+ } while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
+ if (ret == -1)
+ boost::process::detail::throw_last_error("waitpid(2) failed");
+}
+
+inline void wait(const group_handle &p, std::error_code &ec) noexcept
+{
+ pid_t ret;
+ int status;
+
+ do
+ {
+ ret = ::waitpid(-p.grp, &status, 0);
+ }
+ while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
+
+ if (ret == -1)
+ ec = boost::process::detail::get_last_error();
+ else
+ ec.clear();
+
+}
+
+template< class Rep, class Period >
+inline bool wait_for(
+ const group_handle &p,
+ const std::chrono::duration<Rep, Period>& rel_time)
+{
+
+ pid_t ret;
+ int status;
+
+ auto start = std::chrono::system_clock::now();
+ auto time_out = start + rel_time;
+
+ bool time_out_occured = false;
+ do
+ {
+ ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
+ if (std::chrono::system_clock::now() >= time_out)
+ {
+ time_out_occured = true;
+ break;
+ }
+ }
+ while (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status)));
+
+
+ if (ret == -1)
+ boost::process::detail::throw_last_error("waitpid(2) failed");
+
+
+ return !time_out_occured;
+}
+
+
+template< class Rep, class Period >
+inline bool wait_for(
+ const group_handle &p,
+ const std::chrono::duration<Rep, Period>& rel_time,
+ std::error_code & ec) noexcept
+{
+
+ pid_t ret;
+ int status;
+
+ auto start = std::chrono::system_clock::now();
+ auto time_out = start + rel_time;
+
+ bool time_out_occured = false;
+ do
+ {
+ ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
+ if (std::chrono::system_clock::now() >= time_out)
+ {
+ time_out_occured = true;
+ break;
+ }
+ }
+ while (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status)));
+
+
+ if (ret == -1)
+ ec = boost::process::detail::get_last_error();
+ else
+ ec.clear();
+
+ return !time_out_occured;
+}
+
+
+
+template< class Rep, class Period >
+inline bool wait_until(
+ const group_handle &p,
+ const std::chrono::duration<Rep, Period>& time_out)
+{
+
+ pid_t ret;
+ int status;
+
+ auto start = std::chrono::system_clock::now();
+
+ bool time_out_occured = false;
+ do
+ {
+ ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
+ if (std::chrono::system_clock::now() >= time_out)
+ {
+ time_out_occured = true;
+ break;
+ }
+ }
+ while (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status)));
+
+
+ if (ret == -1)
+ boost::process::detail::throw_last_error("waitpid(2) failed");
+
+
+ return !time_out_occured;
+}
+
+
+template< class Rep, class Period >
+inline bool wait_until(
+ const group_handle &p,
+ const std::chrono::duration<Rep, Period>& time_out,
+ std::error_code & ec) noexcept
+{
+
+ pid_t ret;
+ int status;
+
+ auto start = std::chrono::system_clock::now();
+
+ bool time_out_occured = false;
+ do
+ {
+ ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
+ if (std::chrono::system_clock::now() >= time_out)
+ {
+ time_out_occured = true;
+ break;
+ }
+ }
+ while (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status)));
+
+
+ if (ret == -1)
+ ec = boost::process::detail::get_last_error();
+ else
+ ec.clear();
+
+ return !time_out_occured;
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/throw_on_error.hpp b/boost/process/detail/throw_on_error.hpp
new file mode 100644
index 0000000000..071aaec0cf
--- /dev/null
+++ b/boost/process/detail/throw_on_error.hpp
@@ -0,0 +1,36 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_INITIALIZERS_THROW_ON_ERROR_HPP
+#define BOOST_PROCESS_DETAIL_INITIALIZERS_THROW_ON_ERROR_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/handler_base.hpp>
+
+namespace boost { namespace process { namespace detail {
+
+struct throw_on_error_ : ::boost::process::detail::handler
+{
+ template <class Executor>
+ void on_error(Executor& exec, const std::error_code & ec) const
+ {
+ throw process_error(ec, "process creation failed");
+ }
+
+ const throw_on_error_ &operator()() const {return *this;}
+};
+
+}
+
+constexpr boost::process::detail::throw_on_error_ throw_on_error;
+
+}}
+
+#endif
diff --git a/boost/process/detail/traits.hpp b/boost/process/detail/traits.hpp
new file mode 100644
index 0000000000..a1b0e6b19b
--- /dev/null
+++ b/boost/process/detail/traits.hpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_TRAITS_HPP_
+#define BOOST_PROCESS_TRAITS_HPP_
+
+#include <boost/process/detail/traits/decl.hpp>
+#include <boost/process/detail/traits/async.hpp>
+#include <boost/process/detail/traits/cmd_or_exe.hpp>
+#include <boost/process/detail/traits/env.hpp>
+#include <boost/process/detail/traits/error.hpp>
+#include <boost/process/detail/traits/wchar_t.hpp>
+
+#endif /* BOOST_PROCESS_TRAITS_HPP_ */
diff --git a/boost/process/detail/traits/async.hpp b/boost/process/detail/traits/async.hpp
new file mode 100644
index 0000000000..da7ed79aae
--- /dev/null
+++ b/boost/process/detail/traits/async.hpp
@@ -0,0 +1,34 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_TRAITS_ASYNC_HPP_
+#define BOOST_PROCESS_DETAIL_TRAITS_ASYNC_HPP_
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/traits/decl.hpp>
+
+namespace boost { namespace asio {
+
+class io_service;
+}}
+
+namespace boost { namespace process { namespace detail {
+
+struct async_tag {};
+
+template<>
+struct initializer_builder<async_tag>;
+
+template<> struct initializer_tag<::boost::asio::io_service> { typedef async_tag type;};
+
+
+
+
+}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */
diff --git a/boost/process/detail/traits/cmd_or_exe.hpp b/boost/process/detail/traits/cmd_or_exe.hpp
new file mode 100644
index 0000000000..f6a8ae7cd3
--- /dev/null
+++ b/boost/process/detail/traits/cmd_or_exe.hpp
@@ -0,0 +1,85 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_TRAITS_CMD_OR_EXE_HPP_
+#define BOOST_PROCESS_DETAIL_TRAITS_CMD_OR_EXE_HPP_
+
+#include <string>
+#include <vector>
+#include <type_traits>
+#include <initializer_list>
+#include <boost/filesystem/path.hpp>
+#include <boost/process/detail/traits/decl.hpp>
+namespace boost { namespace process { namespace detail {
+
+template<typename Char>
+struct cmd_or_exe_tag {};
+
+struct shell_;
+
+
+template<> struct initializer_tag<const char* > { typedef cmd_or_exe_tag<char> type;};
+template<> struct initializer_tag<const wchar_t* > { typedef cmd_or_exe_tag<wchar_t> type;};
+
+template<> struct initializer_tag<char* > { typedef cmd_or_exe_tag<char> type;};
+template<> struct initializer_tag<wchar_t* > { typedef cmd_or_exe_tag<wchar_t> type;};
+
+template<std::size_t Size> struct initializer_tag<const char [Size]> { typedef cmd_or_exe_tag<char> type;};
+template<std::size_t Size> struct initializer_tag<const wchar_t [Size]> { typedef cmd_or_exe_tag<wchar_t> type;};
+
+template<std::size_t Size> struct initializer_tag<const char (&)[Size]> { typedef cmd_or_exe_tag<char> type;};
+template<std::size_t Size> struct initializer_tag<const wchar_t (&)[Size]> { typedef cmd_or_exe_tag<wchar_t> type;};
+
+template<> struct initializer_tag<std::basic_string<char >> { typedef cmd_or_exe_tag<char> type;};
+template<> struct initializer_tag<std::basic_string<wchar_t >> { typedef cmd_or_exe_tag<wchar_t> type;};
+
+template<> struct initializer_tag<std::vector<std::basic_string<char >>> { typedef cmd_or_exe_tag<char> type;};
+template<> struct initializer_tag<std::vector<std::basic_string<wchar_t >>> { typedef cmd_or_exe_tag<wchar_t> type;};
+
+template<> struct initializer_tag<std::initializer_list<std::basic_string<char >>> { typedef cmd_or_exe_tag<char> type;};
+template<> struct initializer_tag<std::initializer_list<std::basic_string<wchar_t >>> { typedef cmd_or_exe_tag<wchar_t> type;};
+
+template<> struct initializer_tag<std::vector<char *>> { typedef cmd_or_exe_tag<char> type;};
+template<> struct initializer_tag<std::vector<wchar_t *>> { typedef cmd_or_exe_tag<wchar_t> type;};
+
+template<> struct initializer_tag<std::initializer_list<char *>> { typedef cmd_or_exe_tag<char> type;};
+template<> struct initializer_tag<std::initializer_list<wchar_t *>> { typedef cmd_or_exe_tag<wchar_t> type;};
+
+template<> struct initializer_tag<std::initializer_list<const char *>> { typedef cmd_or_exe_tag<char> type;};
+template<> struct initializer_tag<std::initializer_list<const wchar_t *>> { typedef cmd_or_exe_tag<wchar_t> type;};
+
+template<> struct initializer_tag<shell_>
+{
+ typedef cmd_or_exe_tag<typename boost::filesystem::path::value_type> type;
+};
+
+template<> struct initializer_tag<boost::filesystem::path>
+{
+ typedef cmd_or_exe_tag<typename boost::filesystem::path::value_type> type;
+};
+
+template <typename Char>
+struct exe_setter_;
+template <typename Char, bool Append = false>
+struct arg_setter_;
+
+template <typename Char, bool Append>
+struct initializer_tag<arg_setter_<Char, Append>> { typedef cmd_or_exe_tag<Char> type;};
+
+template<typename Char> struct initializer_tag<exe_setter_<Char>> { typedef cmd_or_exe_tag<Char> type;};
+
+template<>
+struct initializer_builder<cmd_or_exe_tag<char>>;
+
+template<>
+struct initializer_builder<cmd_or_exe_tag<wchar_t>>;
+
+
+}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_STRING_TRAITS_HPP_ */
diff --git a/boost/process/detail/traits/decl.hpp b/boost/process/detail/traits/decl.hpp
new file mode 100644
index 0000000000..48f8022f73
--- /dev/null
+++ b/boost/process/detail/traits/decl.hpp
@@ -0,0 +1,76 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_TRAITS_DECL_HPP_
+#define BOOST_PROCESS_DETAIL_TRAITS_DECL_HPP_
+
+#include <boost/process/detail/config.hpp>
+#include <boost/none.hpp>
+#include <type_traits>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/handler.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/handler.hpp>
+#endif
+
+
+namespace boost { namespace process { namespace detail {
+
+
+template<typename T>
+struct is_initializer : std::is_base_of<handler_base, T> {};
+
+
+template<typename T>
+struct is_initializer<T&> : std::is_base_of<handler_base, T> {};
+
+
+template<typename T>
+struct initializer_tag;// { typedef void type; };
+
+
+//remove const
+template<typename T>
+struct initializer_tag<const T> { typedef typename initializer_tag<T>::type type; };
+
+//remove &
+template<typename T>
+struct initializer_tag<T&> { typedef typename initializer_tag<T>::type type; };
+
+//remove const &
+template<typename T>
+struct initializer_tag<const T&> { typedef typename initializer_tag<T>::type type; };
+
+template<typename T>
+struct initializer_builder;
+
+
+template<typename First, typename ...Args>
+struct valid_argument_list;
+
+template<typename First>
+struct valid_argument_list<First>
+{
+ constexpr static bool value = is_initializer<First>::value || !std::is_void<typename initializer_tag<First>::type>::value;
+ typedef std::integral_constant<bool, value> type;
+};
+
+template<typename First, typename ...Args>
+struct valid_argument_list
+{
+ constexpr static bool my_value = is_initializer<First>::value || !std::is_void<typename initializer_tag<First>::type>::value;
+ constexpr static bool value = valid_argument_list<Args...>::value && my_value;
+ typedef std::integral_constant<bool, value> type;
+};
+
+
+
+}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */
diff --git a/boost/process/detail/traits/env.hpp b/boost/process/detail/traits/env.hpp
new file mode 100644
index 0000000000..ccdcad046a
--- /dev/null
+++ b/boost/process/detail/traits/env.hpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_TRAITS_ENV_HPP_
+#define BOOST_PROCESS_DETAIL_TRAITS_ENV_HPP_
+
+
+#include <boost/process/detail/traits/decl.hpp>
+
+
+namespace boost { namespace process {
+
+template<typename Char>
+class basic_environment;
+
+template<typename Char>
+class basic_native_environment;
+
+namespace detail {
+
+template<typename Char>
+struct env_tag {};
+
+
+
+
+template<typename Char> struct env_set;
+template<typename Char> struct env_append;
+
+template<typename Char> struct env_reset;
+template<typename Char> struct env_init;
+
+
+template<typename Char> struct initializer_tag<env_set<Char>> { typedef env_tag<Char> type; };
+template<typename Char> struct initializer_tag<env_append<Char>> { typedef env_tag<Char> type; };
+
+template<typename Char> struct initializer_tag<env_reset<Char>> { typedef env_tag<Char> type;};
+template<typename Char> struct initializer_tag<env_init <Char>> { typedef env_tag<Char> type;};
+
+template<typename Char> struct initializer_tag<::boost::process::basic_environment<Char>> { typedef env_tag<Char> type; };
+template<typename Char> struct initializer_tag<::boost::process::basic_native_environment<Char>> { typedef env_tag<Char> type; };
+
+template<> struct initializer_builder<env_tag<char>>;
+template<> struct initializer_builder<env_tag<wchar_t>>;
+
+}
+
+
+}}
+
+#endif /* INCLUDE_BOOST_PROCESS_DETAIL_ENV_HPP_ */
diff --git a/boost/process/detail/traits/error.hpp b/boost/process/detail/traits/error.hpp
new file mode 100644
index 0000000000..2d1912bda9
--- /dev/null
+++ b/boost/process/detail/traits/error.hpp
@@ -0,0 +1,27 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_TRAITS_ERROR_HPP_
+#define BOOST_PROCESS_DETAIL_TRAITS_ERROR_HPP_
+
+#include <boost/process/detail/config.hpp>
+#include <system_error>
+#include <boost/process/detail/traits/decl.hpp>
+
+
+
+namespace boost { namespace process { namespace detail {
+
+struct error_tag;
+
+template<>
+struct initializer_tag<std::error_code>;
+
+}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */
diff --git a/boost/process/detail/traits/group.hpp b/boost/process/detail/traits/group.hpp
new file mode 100644
index 0000000000..3e7897c689
--- /dev/null
+++ b/boost/process/detail/traits/group.hpp
@@ -0,0 +1,37 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_TRAITS_GROUP_HPP_
+#define BOOST_PROCESS_DETAIL_TRAITS_GROUP_HPP_
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/traits/decl.hpp>
+
+
+
+namespace boost { namespace process {
+
+struct group;
+
+namespace detail {
+
+
+struct group_tag {};
+
+template<>
+struct make_initializer_t<group_tag>;
+
+
+template<> struct initializer_tag_t<::boost::process::group> { typedef group_tag type;};
+
+
+
+
+}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */
diff --git a/boost/process/detail/traits/wchar_t.hpp b/boost/process/detail/traits/wchar_t.hpp
new file mode 100644
index 0000000000..812a92cf13
--- /dev/null
+++ b/boost/process/detail/traits/wchar_t.hpp
@@ -0,0 +1,274 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_TRAITS_WCHAR_T_HPP_
+#define BOOST_PROCESS_DETAIL_TRAITS_WCHAR_T_HPP_
+
+#include <boost/process/detail/traits/decl.hpp>
+#include <boost/process/detail/traits/cmd_or_exe.hpp>
+#include <boost/process/detail/traits/env.hpp>
+#include <boost/process/locale.hpp>
+
+namespace boost { namespace process { namespace detail {
+
+//template
+
+template<typename T> struct is_wchar_t : std::false_type {};
+
+template<> struct is_wchar_t<boost::filesystem::path> : std::is_same<typename boost::filesystem::path::value_type, wchar_t>
+{
+};
+
+template<> struct is_wchar_t<const wchar_t* > : std::true_type {};
+
+template<> struct is_wchar_t<wchar_t* > : std::true_type {};
+
+template<std::size_t Size> struct is_wchar_t<const wchar_t [Size]> : std::true_type {};
+template<std::size_t Size> struct is_wchar_t<const wchar_t (&)[Size]> : std::true_type {};
+
+template<> struct is_wchar_t<std::wstring> : std::true_type {};
+template<> struct is_wchar_t<std::vector<std::wstring>> : std::true_type {};
+template<> struct is_wchar_t<std::initializer_list<std::wstring>> : std::true_type {};
+template<> struct is_wchar_t<std::vector<wchar_t *>> : std::true_type {};
+template<> struct is_wchar_t<std::initializer_list<wchar_t *>> : std::true_type {};
+
+
+
+template<typename Char, typename T>
+struct char_converter
+{
+ static T& conv(T & in)
+ {
+ return in;
+ }
+ static T&& conv(T&& in)
+ {
+ return std::move(in);
+ }
+ static const T& conv(const T & in)
+ {
+ return in;
+ }
+};
+
+template<typename Char, typename T>
+using char_converter_t = char_converter<Char,
+ typename std::remove_cv<typename std::remove_reference<T>::type>::type>;
+
+
+template<>
+struct char_converter<char, const wchar_t*>
+{
+ static std::string conv(const wchar_t* in)
+ {
+ std::size_t size = 0;
+ while (in[size] != L'\0') size++;
+ return ::boost::process::detail::convert(in, in + size);
+ }
+};
+
+template<>
+struct char_converter<char, wchar_t*>
+{
+ static std::string conv(wchar_t* in)
+ {
+ std::size_t size = 0;
+ while (in[size] != L'\0') size++;
+ return ::boost::process::detail::convert(in, in + size);
+ }
+};
+
+template<std::size_t Size>
+struct char_converter<char, wchar_t[Size]>
+{
+ static std::string conv(const wchar_t(&in)[Size])
+ {
+ return ::boost::process::detail::convert(in, in + Size -1);
+ }
+};
+
+template<>
+struct char_converter<wchar_t, const char*>
+{
+ static std::wstring conv(const char* in)
+ {
+ std::size_t size = 0;
+ while (in[size] != '\0') size++;
+ return ::boost::process::detail::convert(in, in + size);
+ }
+};
+
+template<>
+struct char_converter<wchar_t, char*>
+{
+ static std::wstring conv(char* in)
+ {
+ std::size_t size = 0;
+ while (in[size] != '\0') size++;
+ return ::boost::process::detail::convert(in, in + size);
+ }
+};
+
+
+template<std::size_t Size>
+struct char_converter<wchar_t, char[Size]>
+{
+ static std::wstring conv(const char(&in)[Size])
+ {
+ return ::boost::process::detail::convert(in, in + Size -1);
+ }
+};
+
+//all the containers.
+template<>
+struct char_converter<wchar_t, std::string>
+{
+ static std::wstring conv(const std::string & in)
+ {
+ return ::boost::process::detail::convert(in);
+ }
+};
+
+template<>
+struct char_converter<char, std::wstring>
+{
+ static std::string conv(const std::wstring & in)
+ {
+ return ::boost::process::detail::convert(in);
+ }
+};
+
+template<>
+struct char_converter<wchar_t, std::vector<std::string>>
+{
+ static std::vector<std::wstring> conv(const std::vector<std::string> & in)
+ {
+ std::vector<std::wstring> ret(in.size());
+ std::transform(in.begin(), in.end(), ret.begin(),
+ [](const std::string & st)
+ {
+ return convert(st);
+ });
+ return ret;
+ }
+};
+
+template<>
+struct char_converter<wchar_t, std::initializer_list<std::string>>
+{
+ static std::vector<std::wstring> conv(const std::initializer_list<std::string> & in)
+ {
+ std::vector<std::wstring> ret(in.size());
+ std::transform(in.begin(), in.end(), ret.begin(),
+ [](const std::string & st)
+ {
+ return convert(st);
+ });
+ return ret;
+ }
+};
+
+template<>
+struct char_converter<wchar_t, std::vector<char* >>
+{
+ static std::vector<std::wstring> conv(const std::vector<char* > & in)
+ {
+ std::vector<std::wstring> ret(in.size());
+ std::transform(in.begin(), in.end(), ret.begin(),
+ [](const char* st)
+ {
+ std::size_t sz = 0;
+ while (st[sz] != '\0') sz++;
+ return convert(st, st + sz);
+ });
+ return ret;
+ }
+};
+
+template<>
+struct char_converter<wchar_t, std::initializer_list<char *>>
+{
+ static std::vector<std::wstring> conv(const std::initializer_list<char * > & in)
+ {
+ std::vector<std::wstring> ret(in.size());
+ std::transform(in.begin(), in.end(), ret.begin(),
+ [](const char* st)
+ {
+ std::size_t sz = 0;
+ while (st[sz] != '\0') sz++;
+ return convert(st, st + sz);
+ });
+ return ret;
+ }
+};
+
+template<>
+struct char_converter<char, std::vector<std::wstring>>
+{
+ static std::vector<std::string> conv(const std::vector<std::wstring> & in)
+ {
+ std::vector<std::string> ret(in.size());
+ std::transform(in.begin(), in.end(), ret.begin(),
+ [](const std::wstring & st)
+ {
+ return convert(st);
+ });
+ return ret;
+ }
+};
+
+template<>
+struct char_converter<char, std::initializer_list<std::wstring>>
+{
+ static std::vector<std::string> conv(const std::initializer_list<std::wstring> & in)
+ {
+ std::vector<std::string> ret(in.size());
+ std::transform(in.begin(), in.end(), ret.begin(),
+ [](const std::wstring & st)
+ {
+ return convert(st);
+ });
+ return ret;
+ }
+};
+
+template<>
+struct char_converter<char, std::vector<wchar_t* >>
+{
+ static std::vector<std::string> conv(const std::vector<wchar_t* > & in)
+ {
+ std::vector<std::string> ret(in.size());
+ std::transform(in.begin(), in.end(), ret.begin(),
+ [](const wchar_t* st)
+ {
+ std::size_t sz = 0;
+ while (st[sz] != L'\0') sz++;
+ return convert(st, st + sz);
+ });
+ return ret;
+ }
+};
+
+template<>
+struct char_converter<char, std::initializer_list<wchar_t * >>
+{
+ static std::vector<std::string> conv(const std::initializer_list<wchar_t *> & in)
+ {
+ std::vector<std::string> ret(in.size());
+ std::transform(in.begin(), in.end(), ret.begin(),
+ [](const wchar_t* st)
+ {
+ std::size_t sz = 0;
+ while (st[sz] != L'\0') sz++;
+ return convert(st, st + sz);
+ });
+ return ret;
+ }
+};
+
+
+}}}
+#endif /* BOOST_PROCESS_DETAIL_TRAITS_WCHAR_T_HPP_ */
diff --git a/boost/process/detail/windows/asio_fwd.hpp b/boost/process/detail/windows/asio_fwd.hpp
new file mode 100644
index 0000000000..f7667db101
--- /dev/null
+++ b/boost/process/detail/windows/asio_fwd.hpp
@@ -0,0 +1,71 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_ASIO_FWD_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_ASIO_FWD_HPP_
+
+#include <memory>
+
+namespace boost { namespace asio {
+
+class mutable_buffer;
+class mutable_buffers_1;
+class const_buffer;
+class const_buffers_1;
+
+template<typename Allocator>
+class basic_streambuf;
+
+typedef basic_streambuf<std::allocator<char>> streambuf;
+class io_service;
+
+template <typename Handler>
+class basic_yield_context;
+
+namespace windows {
+
+class stream_handle_service;
+
+template <typename StreamHandleService>
+class basic_stream_handle;
+
+typedef basic_stream_handle<stream_handle_service> stream_handle;
+
+
+class object_handle_service;
+
+template <typename ObjectHandleService>
+class basic_object_handle;
+
+typedef basic_object_handle<object_handle_service> object_handle;
+
+} //windows
+} //asio
+
+namespace process { namespace detail { namespace windows {
+
+class async_pipe;
+
+template<typename T>
+struct async_in_buffer;
+
+template<int p1, int p2, typename Buffer>
+struct async_out_buffer;
+
+template<int p1, int p2, typename Type>
+struct async_out_future;
+
+} // windows
+} // detail
+
+using ::boost::process::detail::windows::async_pipe;
+
+} // process
+} // boost
+
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ASIO_FWD_HPP_ */
diff --git a/boost/process/detail/windows/async_handler.hpp b/boost/process/detail/windows/async_handler.hpp
new file mode 100644
index 0000000000..197c264126
--- /dev/null
+++ b/boost/process/detail/windows/async_handler.hpp
@@ -0,0 +1,40 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_
+#define BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_
+
+#include <boost/process/detail/windows/handler.hpp>
+#include <type_traits>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+struct require_io_service {};
+
+struct async_handler : handler_base_ext, require_io_service
+{
+};
+
+template<typename T>
+struct is_async_handler : std::is_base_of<async_handler, T> {};
+template<typename T>
+struct is_async_handler<T&> : std::is_base_of<async_handler, T> {};
+template<typename T>
+struct is_async_handler<const T&> : std::is_base_of<async_handler, T> {};
+
+template<typename T>
+struct does_require_io_service : std::is_base_of<require_io_service, T> {};
+
+template<typename T>
+struct does_require_io_service<T&> : std::is_base_of<require_io_service, T> {};
+
+template<typename T>
+struct does_require_io_service<const T&> : std::is_base_of<require_io_service, T> {};
+
+
+}}}}
+
+#endif /* BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_ */
diff --git a/boost/process/detail/windows/async_in.hpp b/boost/process/detail/windows/async_in.hpp
new file mode 100644
index 0000000000..4c498612d3
--- /dev/null
+++ b/boost/process/detail/windows/async_in.hpp
@@ -0,0 +1,105 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_IN_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_IN_HPP
+
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/detail/winapi/handle_info.hpp>
+#include <boost/detail/winapi/error_codes.hpp>
+
+#include <boost/asio/write.hpp>
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/windows/async_handler.hpp>
+#include <boost/process/detail/windows/asio_fwd.hpp>
+#include <boost/process/async_pipe.hpp>
+#include <memory>
+#include <future>
+
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+
+template<typename Buffer>
+struct async_in_buffer : ::boost::process::detail::windows::handler_base_ext,
+ ::boost::process::detail::windows::require_io_service
+{
+ Buffer & buf;
+
+ std::shared_ptr<std::promise<void>> promise;
+ async_in_buffer operator>(std::future<void> & fut)
+ {
+ promise = std::make_shared<std::promise<void>>();
+ fut = promise->get_future(); return std::move(*this);
+ }
+
+ std::shared_ptr<boost::process::async_pipe> pipe;
+
+ async_in_buffer(Buffer & buf) : buf(buf)
+ {
+ }
+ template <typename Executor>
+ inline void on_success(Executor&)
+ {
+ auto pipe = this->pipe;
+
+ if (this->promise)
+ {
+ auto promise = this->promise;
+
+ boost::asio::async_write(*pipe, buf,
+ [promise](const boost::system::error_code & ec, std::size_t)
+ {
+ if (ec && (ec.value() != ::boost::detail::winapi::ERROR_BROKEN_PIPE_))
+ {
+ std::error_code e(ec.value(), std::system_category());
+ promise->set_exception(std::make_exception_ptr(process_error(e)));
+ }
+ promise->set_value();
+ });
+ }
+ else
+ boost::asio::async_write(*pipe, buf,
+ [pipe](const boost::system::error_code&, std::size_t){});
+
+ std::move(*pipe).source().close();
+
+
+ this->pipe = nullptr;
+ }
+
+ template<typename Executor>
+ void on_error(Executor &, const std::error_code &) const
+ {
+ ::boost::detail::winapi::CloseHandle(pipe->native_source());
+ }
+
+ template <typename WindowsExecutor>
+ void on_setup(WindowsExecutor &exec)
+ {
+ if (!pipe)
+ pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
+
+ ::boost::detail::winapi::HANDLE_ source_handle = std::move(*pipe).source().native_handle();
+
+ boost::detail::winapi::SetHandleInformation(source_handle,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ exec.startup_info.hStdInput = source_handle;
+ exec.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
+ exec.inherit_handles = true;
+ }
+};
+
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/async_out.hpp b/boost/process/detail/windows/async_out.hpp
new file mode 100644
index 0000000000..435f56ebd6
--- /dev/null
+++ b/boost/process/detail/windows/async_out.hpp
@@ -0,0 +1,176 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_OUT_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_OUT_HPP
+
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/detail/winapi/handle_info.hpp>
+#include <boost/asio/read.hpp>
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/windows/asio_fwd.hpp>
+#include <boost/detail/winapi/error_codes.hpp>
+
+#include <istream>
+#include <memory>
+#include <exception>
+#include <future>
+
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+
+template <typename Executor>
+inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 1>, std::integral_constant<int, -1>)
+{
+ boost::detail::winapi::SetHandleInformation(handle,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ e.startup_info.hStdOutput = handle;
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+}
+
+template <typename Executor>
+inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 2>, std::integral_constant<int, -1>)
+{
+ boost::detail::winapi::SetHandleInformation(handle,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+
+ e.startup_info.hStdError = handle;
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+}
+
+template <typename Executor>
+inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 1>, std::integral_constant<int, 2>)
+{
+ boost::detail::winapi::SetHandleInformation(handle,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ e.startup_info.hStdOutput = handle;
+ e.startup_info.hStdError = handle;
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+}
+
+template<int p1, int p2, typename Buffer>
+struct async_out_buffer : ::boost::process::detail::windows::handler_base_ext,
+ ::boost::process::detail::windows::require_io_service
+{
+ Buffer & buf;
+
+ std::shared_ptr<boost::process::async_pipe> pipe;
+
+
+ async_out_buffer(Buffer & buf) : buf(buf)
+ {
+ }
+ template <typename Executor>
+ inline void on_success(Executor&)
+ {
+ auto pipe = this->pipe;
+ boost::asio::async_read(*pipe, buf,
+ [pipe](const boost::system::error_code&, std::size_t){});
+ std::move(*pipe).sink().close();
+ this->pipe = nullptr;
+
+ }
+
+ template<typename Executor>
+ void on_error(Executor &, const std::error_code &) const
+ {
+ std::move(*pipe).sink().close();
+ }
+
+ template <typename WindowsExecutor>
+ void on_setup(WindowsExecutor &exec)
+ {
+ if (!pipe)
+ pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
+ apply_out_handles(exec, std::move(*pipe).sink().native_handle(),
+ std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
+ }
+};
+
+
+
+template<int p1, int p2, typename Type>
+struct async_out_future : ::boost::process::detail::windows::handler_base_ext,
+ ::boost::process::detail::windows::require_io_service
+{
+ std::shared_ptr<boost::process::async_pipe> pipe;
+ std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>();
+ std::shared_ptr<boost::asio::streambuf> buffer = std::make_shared<boost::asio::streambuf>();
+
+
+ async_out_future(std::future<Type> & fut)
+ {
+ fut = promise->get_future();
+ }
+ template <typename Executor>
+ inline void on_success(Executor&)
+ {
+ auto pipe = this->pipe;
+ auto buffer = this->buffer;
+ auto promise = this->promise;
+ std::move(*pipe).sink().close();
+ boost::asio::async_read(*pipe, *buffer,
+ [pipe, buffer, promise](const boost::system::error_code& ec, std::size_t)
+ {
+ if (ec && (ec.value() != ::boost::detail::winapi::ERROR_BROKEN_PIPE_))
+ {
+ std::error_code e(ec.value(), std::system_category());
+ promise->set_exception(std::make_exception_ptr(process_error(e)));
+ }
+ else
+ {
+ std::istream is (buffer.get());
+ Type arg;
+ arg.resize(buffer->size());
+ is.read(&*arg.begin(), buffer->size());
+
+ promise->set_value(std::move(arg));
+
+
+ }
+ });
+ this->pipe = nullptr;
+ this->buffer = nullptr;
+ this->promise = nullptr;
+
+
+ }
+
+ template<typename Executor>
+ void on_error(Executor &, const std::error_code &) const
+ {
+ std::move(*pipe).sink().close();
+ }
+
+ template <typename WindowsExecutor>
+ void on_setup(WindowsExecutor &exec)
+ {
+ if (!pipe)
+ pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
+
+ apply_out_handles(exec, std::move(*pipe).sink().native_handle(),
+ std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
+ }
+};
+
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/async_pipe.hpp b/boost/process/detail/windows/async_pipe.hpp
new file mode 100644
index 0000000000..ca4f3559d0
--- /dev/null
+++ b/boost/process/detail/windows/async_pipe.hpp
@@ -0,0 +1,415 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_ASYNC_PIPE_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_ASYNC_PIPE_HPP_
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/pipes.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/detail/winapi/file_management.hpp>
+#include <boost/detail/winapi/get_last_error.hpp>
+#include <boost/detail/winapi/access_rights.hpp>
+#include <boost/detail/winapi/process.hpp>
+#include <boost/process/detail/windows/basic_pipe.hpp>
+#include <boost/asio/windows/stream_handle.hpp>
+#include <system_error>
+#include <string>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+inline std::string make_pipe_name()
+{
+ std::string name = "\\\\.\\pipe\\boost_process_auto_pipe_";
+
+ auto pid = ::boost::detail::winapi::GetCurrentProcessId();
+
+ static unsigned long long cnt = 0;
+ name += std::to_string(pid);
+ name += "_";
+ name += std::to_string(cnt++);
+
+ return name;
+}
+
+class async_pipe
+{
+ ::boost::asio::windows::stream_handle _source;
+ ::boost::asio::windows::stream_handle _sink ;
+public:
+ typedef ::boost::detail::winapi::HANDLE_ native_handle_type;
+ typedef ::boost::asio::windows::stream_handle handle_type;
+
+ inline async_pipe(boost::asio::io_service & ios,
+ const std::string & name = make_pipe_name())
+ : async_pipe(ios, ios, name) {}
+
+ inline async_pipe(boost::asio::io_service & ios_source,
+ boost::asio::io_service & ios_sink,
+ const std::string & name = make_pipe_name());
+
+ inline async_pipe(const async_pipe& rhs);
+ async_pipe(async_pipe&& rhs) : _source(std::move(rhs._source)), _sink(std::move(rhs._sink))
+ {
+ rhs._source.assign (::boost::detail::winapi::INVALID_HANDLE_VALUE_);
+ rhs._sink .assign (::boost::detail::winapi::INVALID_HANDLE_VALUE_);
+ }
+ template<class CharT, class Traits = std::char_traits<CharT>>
+ explicit async_pipe(::boost::asio::io_service & ios_source,
+ ::boost::asio::io_service & ios_sink,
+ const basic_pipe<CharT, Traits> & p)
+ : _source(ios_source, p.native_source()), _sink(ios_sink, p.native_sink())
+ {
+ }
+
+ template<class CharT, class Traits = std::char_traits<CharT>>
+ explicit async_pipe(boost::asio::io_service & ios, const basic_pipe<CharT, Traits> & p)
+ : async_pipe(ios, ios, p)
+ {
+ }
+
+ template<class CharT, class Traits = std::char_traits<CharT>>
+ inline async_pipe& operator=(const basic_pipe<CharT, Traits>& p);
+ inline async_pipe& operator=(const async_pipe& rhs);
+
+ inline async_pipe& operator=(async_pipe&& rhs);
+
+ ~async_pipe()
+ {
+ if (_sink .native() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::detail::winapi::CloseHandle(_sink.native());
+ if (_source.native() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::detail::winapi::CloseHandle(_source.native());
+ }
+
+ template<class CharT, class Traits = std::char_traits<CharT>>
+ inline explicit operator basic_pipe<CharT, Traits>() const;
+
+ void cancel()
+ {
+ if (_sink.is_open())
+ _sink.cancel();
+ if (_source.is_open())
+ _source.cancel();
+ }
+
+ void close()
+ {
+ if (_sink.is_open())
+ {
+ _sink.close();
+ _sink = handle_type(_sink.get_io_service());
+ }
+ if (_source.is_open())
+ {
+ _source.close();
+ _source = handle_type(_source.get_io_service());
+ }
+ }
+ void close(boost::system::error_code & ec)
+ {
+ if (_sink.is_open())
+ {
+ _sink.close(ec);
+ _sink = handle_type(_sink.get_io_service());
+ }
+ if (_source.is_open())
+ {
+ _source.close(ec);
+ _source = handle_type(_source.get_io_service());
+ }
+ }
+
+ bool is_open() const
+ {
+ return _sink.is_open() || _source.is_open();
+ }
+ void async_close()
+ {
+ if (_sink.is_open())
+ _sink.get_io_service(). post([this]{_sink.close();});
+ if (_source.is_open())
+ _source.get_io_service().post([this]{_source.close();});
+ }
+
+ template<typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence & buffers)
+ {
+ return _source.read_some(buffers);
+ }
+ template<typename MutableBufferSequence>
+ std::size_t write_some(const MutableBufferSequence & buffers)
+ {
+ return _sink.write_some(buffers);
+ }
+
+ native_handle_type native_source() const {return const_cast<boost::asio::windows::stream_handle&>(_source).native();}
+ native_handle_type native_sink () const {return const_cast<boost::asio::windows::stream_handle&>(_sink ).native();}
+
+ template<typename MutableBufferSequence,
+ typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(
+ ReadHandler, void(boost::system::error_code, std::size_t))
+ async_read_some(
+ const MutableBufferSequence & buffers,
+ ReadHandler &&handler)
+ {
+ _source.async_read_some(buffers, std::forward<ReadHandler>(handler));
+ }
+
+ template<typename ConstBufferSequence,
+ typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(
+ WriteHandler, void(boost::system::error_code, std::size_t))
+ async_write_some(
+ const ConstBufferSequence & buffers,
+ WriteHandler && handler)
+ {
+ _sink.async_write_some(buffers, std::forward<WriteHandler>(handler));
+ }
+
+ const handle_type & sink () const & {return _sink;}
+ const handle_type & source() const & {return _source;}
+
+ handle_type && source() && { return std::move(_source); }
+ handle_type && sink() && { return std::move(_sink); }
+
+ handle_type source(::boost::asio::io_service& ios) &&
+ {
+ ::boost::asio::windows::stream_handle stolen(ios, _source.native_handle());
+ _source.assign(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
+ return stolen;
+ }
+ handle_type sink (::boost::asio::io_service& ios) &&
+ {
+ ::boost::asio::windows::stream_handle stolen(ios, _sink.native_handle());
+ _sink.assign(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
+ return stolen;
+ }
+
+ handle_type source(::boost::asio::io_service& ios) const &
+ {
+ auto proc = ::boost::detail::winapi::GetCurrentProcess();
+
+ ::boost::detail::winapi::HANDLE_ source;
+ auto source_in = const_cast<handle_type&>(_source).native();
+ if (source_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::detail::winapi::DuplicateHandle(
+ proc, source_in, proc, &source, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ return ::boost::asio::windows::stream_handle(ios, source);
+ }
+ handle_type sink (::boost::asio::io_service& ios) const &
+ {
+ auto proc = ::boost::detail::winapi::GetCurrentProcess();
+
+ ::boost::detail::winapi::HANDLE_ sink;
+ auto sink_in = const_cast<handle_type&>(_sink).native();
+ if (sink_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::detail::winapi::DuplicateHandle(
+ proc, sink_in, proc, &sink, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ return ::boost::asio::windows::stream_handle(ios, sink);
+ }
+};
+
+
+
+async_pipe::async_pipe(const async_pipe& p) :
+ _source(const_cast<handle_type&>(p._source).get_io_service()),
+ _sink (const_cast<handle_type&>(p._sink).get_io_service())
+{
+ auto proc = ::boost::detail::winapi::GetCurrentProcess();
+
+ ::boost::detail::winapi::HANDLE_ source;
+ ::boost::detail::winapi::HANDLE_ sink;
+
+ //cannot get the handle from a const object.
+ auto source_in = const_cast<handle_type&>(p._source).native();
+ auto sink_in = const_cast<handle_type&>(p._sink).native();
+
+ if (source_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::detail::winapi::DuplicateHandle(
+ proc, source_in, proc, &source, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ if (sink_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::detail::winapi::DuplicateHandle(
+ proc, sink_in, proc, &sink, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ _source.assign(source);
+ _sink. assign(sink);
+}
+
+
+async_pipe::async_pipe(boost::asio::io_service & ios_source,
+ boost::asio::io_service & ios_sink,
+ const std::string & name) : _source(ios_source), _sink(ios_sink)
+{
+ static constexpr int FILE_FLAG_OVERLAPPED_ = 0x40000000; //temporary
+
+ ::boost::detail::winapi::HANDLE_ source = ::boost::detail::winapi::create_named_pipe(
+ name.c_str(),
+ ::boost::detail::winapi::PIPE_ACCESS_INBOUND_
+ | FILE_FLAG_OVERLAPPED_, //write flag
+ 0, 1, 8192, 8192, 0, nullptr);
+
+
+ if (source == boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::process::detail::throw_last_error("create_named_pipe(" + name + ") failed");
+
+ _source.assign(source);
+
+ ::boost::detail::winapi::HANDLE_ sink = boost::detail::winapi::create_file(
+ name.c_str(),
+ ::boost::detail::winapi::GENERIC_WRITE_, 0, nullptr,
+ ::boost::detail::winapi::OPEN_EXISTING_,
+ FILE_FLAG_OVERLAPPED_, //to allow read
+ nullptr);
+
+ if (sink == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::process::detail::throw_last_error("create_file() failed");
+
+ _sink.assign(sink);
+}
+
+async_pipe& async_pipe::operator=(const async_pipe & p)
+{
+ auto proc = ::boost::detail::winapi::GetCurrentProcess();
+
+ ::boost::detail::winapi::HANDLE_ source;
+ ::boost::detail::winapi::HANDLE_ sink;
+
+ //cannot get the handle from a const object.
+ auto &source_in = const_cast<::boost::asio::windows::stream_handle &>(p._source);
+ auto &sink_in = const_cast<::boost::asio::windows::stream_handle &>(p._sink);
+
+ if (source_in.native() == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::detail::winapi::DuplicateHandle(
+ proc, source_in.native(), proc, &source, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ if (sink_in.native() == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::detail::winapi::DuplicateHandle(
+ proc, sink_in.native(), proc, &sink, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ //so we also assign the io_service
+ _source = ::boost::asio::windows::stream_handle(source_in.get_io_service(), source);
+ _sink = ::boost::asio::windows::stream_handle(source_in.get_io_service(), sink);
+
+ return *this;
+}
+
+async_pipe& async_pipe::operator=(async_pipe && rhs)
+{
+ if (_source.native_handle() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::detail::winapi::CloseHandle(_source.native());
+
+ if (_sink.native_handle() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::detail::winapi::CloseHandle(_sink.native());
+
+ _source.assign(rhs._source.native_handle());
+ _sink .assign(rhs._sink .native_handle());
+ rhs._source.assign(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
+ rhs._sink .assign(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
+ return *this;
+}
+
+template<class CharT, class Traits>
+async_pipe::operator basic_pipe<CharT, Traits>() const
+{
+ auto proc = ::boost::detail::winapi::GetCurrentProcess();
+
+ ::boost::detail::winapi::HANDLE_ source;
+ ::boost::detail::winapi::HANDLE_ sink;
+
+ //cannot get the handle from a const object.
+ auto source_in = const_cast<::boost::asio::windows::stream_handle &>(_source).native();
+ auto sink_in = const_cast<::boost::asio::windows::stream_handle &>(_sink).native();
+
+ if (source_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::detail::winapi::DuplicateHandle(
+ proc, source_in, proc, &source, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ if (sink_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::detail::winapi::DuplicateHandle(
+ proc, sink_in, proc, &sink, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ return basic_pipe<CharT, Traits>{source, sink};
+}
+
+inline bool operator==(const async_pipe & lhs, const async_pipe & rhs)
+{
+ return compare_handles(lhs.native_source(), rhs.native_source()) &&
+ compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+inline bool operator!=(const async_pipe & lhs, const async_pipe & rhs)
+{
+ return !compare_handles(lhs.native_source(), rhs.native_source()) ||
+ !compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+template<class Char, class Traits>
+inline bool operator==(const async_pipe & lhs, const basic_pipe<Char, Traits> & rhs)
+{
+ return compare_handles(lhs.native_source(), rhs.native_source()) &&
+ compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+template<class Char, class Traits>
+inline bool operator!=(const async_pipe & lhs, const basic_pipe<Char, Traits> & rhs)
+{
+ return !compare_handles(lhs.native_source(), rhs.native_source()) ||
+ !compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+template<class Char, class Traits>
+inline bool operator==(const basic_pipe<Char, Traits> & lhs, const async_pipe & rhs)
+{
+ return compare_handles(lhs.native_source(), rhs.native_source()) &&
+ compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+template<class Char, class Traits>
+inline bool operator!=(const basic_pipe<Char, Traits> & lhs, const async_pipe & rhs)
+{
+ return !compare_handles(lhs.native_source(), rhs.native_source()) ||
+ !compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+}}}}
+
+#endif /* INCLUDE_BOOST_PIPE_DETAIL_WINDOWS_ASYNC_PIPE_HPP_ */
diff --git a/boost/process/detail/windows/basic_cmd.hpp b/boost/process/detail/windows/basic_cmd.hpp
new file mode 100644
index 0000000000..176a052368
--- /dev/null
+++ b/boost/process/detail/windows/basic_cmd.hpp
@@ -0,0 +1,164 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_BASIC_CMD_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_BASIC_CMD_HPP_
+
+#include <boost/algorithm/string/trim.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/process/shell.hpp>
+#include <boost/process/detail/windows/handler.hpp>
+
+#include <vector>
+#include <string>
+#include <iterator>
+
+
+namespace boost
+{
+namespace process
+{
+namespace detail
+{
+namespace windows
+{
+
+inline std::string build_args(const std::string & exe, std::vector<std::string> && data)
+{
+ std::string st = exe;
+
+ //put in quotes if it has spaces
+ {
+ boost::replace_all(st, "\"", "\\\"");
+
+ auto it = std::find(st.begin(), st.end(), ' ');
+
+ if (it != st.end())//contains spaces.
+ {
+ st.insert(st.begin(), '"');
+ st += '"';
+ }
+ }
+
+ for (auto & arg : data)
+ {
+ boost::replace_all(arg, "\"", "\\\"");
+
+ auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
+ if (it != arg.end())//ok, contains spaces.
+ {
+ //the first one is put directly onto the output,
+ //because then I don't have to copy the whole string
+ arg.insert(arg.begin(), '"');
+ arg += '"'; //thats the post one.
+ }
+
+ if (!st.empty())//first one does not need a preceeding space
+ st += ' ';
+
+ st += arg;
+ }
+ return st;
+}
+
+inline std::wstring build_args(const std::wstring & exe, std::vector<std::wstring> && data)
+{
+ std::wstring st = exe;
+ for (auto & arg : data)
+ {
+ boost::replace_all(arg, L"\"", L"\\\"");
+
+ auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
+ if (it != arg.end())//ok, contains spaces.
+ {
+ //the first one is put directly onto the output,
+ //because then I don't have to copy the whole string
+ arg.insert(arg.begin(), L'"');
+ arg += L'"'; //thats the post one.
+ }
+
+ if (!st.empty())//first one does not need a preceeding space
+ st += L' ';
+
+ st += arg;
+ }
+ return st;
+}
+
+template<typename Char>
+struct exe_cmd_init : handler_base_ext
+{
+ using value_type = Char;
+ using string_type = std::basic_string<value_type>;
+
+ static const char* c_arg(char) { return "/c";}
+ static const wchar_t* c_arg(wchar_t) { return L"/c";}
+
+ exe_cmd_init(const string_type & exe, bool cmd_only = false)
+ : exe(exe), args({}), cmd_only(cmd_only) {};
+ exe_cmd_init(string_type && exe, bool cmd_only = false)
+ : exe(std::move(exe)), args({}), cmd_only(cmd_only) {};
+
+ exe_cmd_init(string_type && exe, std::vector<string_type> && args)
+ : exe(std::move(exe)), args(build_args(this->exe, std::move(args))), cmd_only(false) {};
+ template <class Executor>
+ void on_setup(Executor& exec) const
+ {
+
+ if (cmd_only && args.empty())
+ exec.cmd_line = exe.c_str();
+ else
+ {
+ exec.exe = exe.c_str();
+ exec.cmd_line = args.c_str();
+ }
+ }
+ static exe_cmd_init<Char> exe_args(string_type && exe, std::vector<string_type> && args)
+ {
+ return exe_cmd_init<Char>(std::move(exe), std::move(args));
+ }
+ static exe_cmd_init<Char> cmd(string_type&& cmd)
+ {
+ return exe_cmd_init<Char>(std::move(cmd), true);
+ }
+ static exe_cmd_init<Char> exe_args_shell(string_type && exe, std::vector<string_type> && args)
+ {
+ std::vector<string_type> args_ = {c_arg(Char()), std::move(exe)};
+ args_.insert(args_.end(), std::make_move_iterator(args.begin()), std::make_move_iterator(args.end()));
+ string_type sh = get_shell(Char());
+
+ return exe_cmd_init<Char>(std::move(sh), std::move(args_));
+ }
+
+ static std:: string get_shell(char) {return shell(). string(codecvt()); }
+ static std::wstring get_shell(wchar_t) {return shell().wstring(codecvt());}
+
+ static exe_cmd_init<Char> cmd_shell(string_type&& cmd)
+ {
+ std::vector<string_type> args = {c_arg(Char()), std::move(cmd)};
+ string_type sh = get_shell(Char());
+
+ return exe_cmd_init<Char>(
+ std::move(sh),
+ std::move(args));
+ }
+private:
+ string_type exe;
+ string_type args;
+ bool cmd_only;
+};
+
+}
+
+
+
+}
+}
+}
+
+
+
+#endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ARGS_HPP_ */
diff --git a/boost/process/detail/windows/basic_pipe.hpp b/boost/process/detail/windows/basic_pipe.hpp
new file mode 100644
index 0000000000..2471e60f6d
--- /dev/null
+++ b/boost/process/detail/windows/basic_pipe.hpp
@@ -0,0 +1,225 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_PIPE_HPP
+#define BOOST_PROCESS_DETAIL_WINDOWS_PIPE_HPP
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/error_codes.hpp>
+#include <boost/detail/winapi/pipes.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/detail/winapi/file_management.hpp>
+#include <boost/detail/winapi/get_last_error.hpp>
+#include <boost/detail/winapi/access_rights.hpp>
+#include <boost/detail/winapi/process.hpp>
+#include <boost/process/detail/windows/compare_handles.hpp>
+#include <system_error>
+#include <string>
+
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+template<class CharT, class Traits = std::char_traits<CharT>>
+class basic_pipe
+{
+ ::boost::detail::winapi::HANDLE_ _source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ ::boost::detail::winapi::HANDLE_ _sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+public:
+ typedef CharT char_type ;
+ typedef Traits traits_type;
+ typedef typename Traits::int_type int_type ;
+ typedef typename Traits::pos_type pos_type ;
+ typedef typename Traits::off_type off_type ;
+ typedef ::boost::detail::winapi::HANDLE_ native_handle_type;
+
+ explicit basic_pipe(::boost::detail::winapi::HANDLE_ source, ::boost::detail::winapi::HANDLE_ sink)
+ : _source(source), _sink(sink) {}
+ inline explicit basic_pipe(const std::string & name);
+ inline basic_pipe(const basic_pipe& p);
+ basic_pipe(basic_pipe&& lhs) : _source(lhs._source), _sink(lhs._sink)
+ {
+ lhs._source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ lhs._sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ }
+ inline basic_pipe& operator=(const basic_pipe& p);
+ inline basic_pipe& operator=(basic_pipe&& lhs);
+ ~basic_pipe()
+ {
+ if (_sink != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::detail::winapi::CloseHandle(_sink);
+ if (_source != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::detail::winapi::CloseHandle(_source);
+ }
+ native_handle_type native_source() const {return _source;}
+ native_handle_type native_sink () const {return _sink;}
+
+ void assign_source(native_handle_type h) { _source = h;}
+ void assign_sink (native_handle_type h) { _sink = h;}
+
+ basic_pipe()
+ {
+ if (!::boost::detail::winapi::CreatePipe(&_source, &_sink, nullptr, 0))
+ throw_last_error("CreatePipe() failed");
+
+ }
+
+ int_type write(const char_type * data, int_type count)
+ {
+ ::boost::detail::winapi::DWORD_ write_len;
+ if (!::boost::detail::winapi::WriteFile(
+ _sink, data, count * sizeof(char_type), &write_len, nullptr
+ ))
+ {
+ auto ec = ::boost::process::detail::get_last_error();
+ if ((ec.value() == ::boost::detail::winapi::ERROR_BROKEN_PIPE_) ||
+ (ec.value() == ::boost::detail::winapi::ERROR_NO_DATA_))
+ return 0;
+ else
+ throw process_error(ec, "WriteFile failed");
+ }
+ return static_cast<int_type>(write_len);
+ }
+ int_type read(char_type * data, int_type count)
+ {
+ ::boost::detail::winapi::DWORD_ read_len;
+ if (!::boost::detail::winapi::ReadFile(
+ _source, data, count * sizeof(char_type), &read_len, nullptr
+ ))
+ {
+ auto ec = ::boost::process::detail::get_last_error();
+ if ((ec.value() == ::boost::detail::winapi::ERROR_BROKEN_PIPE_) ||
+ (ec.value() == ::boost::detail::winapi::ERROR_NO_DATA_))
+ return 0;
+ else
+ throw process_error(ec, "ReadFile failed");
+ }
+ return static_cast<int_type>(read_len);
+ }
+
+ bool is_open()
+ {
+ return (_source != ::boost::detail::winapi::INVALID_HANDLE_VALUE_) ||
+ (_sink != ::boost::detail::winapi::INVALID_HANDLE_VALUE_);
+ }
+
+ void close()
+ {
+ ::boost::detail::winapi::CloseHandle(_source);
+ ::boost::detail::winapi::CloseHandle(_sink);
+ _source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ _sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ }
+};
+
+template<class Char, class Traits>
+basic_pipe<Char, Traits>::basic_pipe(const basic_pipe & p)
+{
+ auto proc = ::boost::detail::winapi::GetCurrentProcess();
+
+ if (p._source == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ _source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::detail::winapi::DuplicateHandle(
+ proc, p._source, proc, &_source, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ if (p._sink == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ _sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::detail::winapi::DuplicateHandle(
+ proc, p._sink, proc, &_sink, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+}
+
+template<class Char, class Traits>
+basic_pipe<Char, Traits>::basic_pipe(const std::string & name)
+{
+ static constexpr int OPEN_EXISTING_ = 3; //temporary.
+ static constexpr int FILE_FLAG_OVERLAPPED_ = 0x40000000; //temporary
+ //static constexpr int FILE_ATTRIBUTE_NORMAL_ = 0x00000080; //temporary
+
+ ::boost::detail::winapi::HANDLE_ source = ::boost::detail::winapi::create_named_pipe(
+ name.c_str(),
+ ::boost::detail::winapi::PIPE_ACCESS_INBOUND_
+ | FILE_FLAG_OVERLAPPED_, //write flag
+ 0, 1, 8192, 8192, 0, nullptr);
+
+ if (source == boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::process::detail::throw_last_error("create_named_pipe() failed");
+
+ ::boost::detail::winapi::HANDLE_ sink = boost::detail::winapi::create_file(
+ name.c_str(),
+ ::boost::detail::winapi::GENERIC_WRITE_, 0, nullptr,
+ OPEN_EXISTING_,
+ FILE_FLAG_OVERLAPPED_, //to allow read
+ nullptr);
+
+ if (sink == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::process::detail::throw_last_error("create_file() failed");
+
+ _source = source;
+ _sink = sink;
+}
+
+template<class Char, class Traits>
+basic_pipe<Char, Traits>& basic_pipe<Char, Traits>::operator=(const basic_pipe & p)
+{
+ auto proc = ::boost::detail::winapi::GetCurrentProcess();
+
+ if (p._source == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ _source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::detail::winapi::DuplicateHandle(
+ proc, p._source, proc, &_source, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ if (p._sink == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ _sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ else if (!::boost::detail::winapi::DuplicateHandle(
+ proc, p._sink, proc, &_sink, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+ throw_last_error("Duplicate Pipe Failed");
+
+ return *this;
+}
+
+template<class Char, class Traits>
+basic_pipe<Char, Traits>& basic_pipe<Char, Traits>::operator=(basic_pipe && lhs)
+{
+ if (_source != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::detail::winapi::CloseHandle(_source);
+
+ if (_sink != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::detail::winapi::CloseHandle(_sink);
+
+ _source = lhs._source;
+ _sink = lhs._sink;
+ lhs._source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ lhs._sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ return *this;
+}
+
+template<class Char, class Traits>
+inline bool operator==(const basic_pipe<Char, Traits> & lhs, const basic_pipe<Char, Traits> & rhs)
+{
+ return compare_handles(lhs.native_source(), rhs.native_source()) &&
+ compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+template<class Char, class Traits>
+inline bool operator!=(const basic_pipe<Char, Traits> & lhs, const basic_pipe<Char, Traits> & rhs)
+{
+ return !compare_handles(lhs.native_source(), rhs.native_source()) ||
+ !compare_handles(lhs.native_sink(), rhs.native_sink());
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/child_handle.hpp b/boost/process/detail/windows/child_handle.hpp
new file mode 100644
index 0000000000..4e809be9fc
--- /dev/null
+++ b/boost/process/detail/windows/child_handle.hpp
@@ -0,0 +1,98 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_CHILD_HPP
+#define BOOST_PROCESS_WINDOWS_CHILD_HPP
+
+#include <boost/move/move.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/jobs.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+typedef int pid_t;
+
+struct child_handle
+{
+ ::boost::detail::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
+
+ explicit child_handle(const ::boost::detail::winapi::PROCESS_INFORMATION_ &pi) :
+ proc_info(pi)
+ {}
+
+ explicit child_handle(pid_t pid) :
+ proc_info{nullptr, nullptr, 0,0}
+ {
+ auto h = ::boost::detail::winapi::OpenProcess(
+ ::boost::detail::winapi::PROCESS_ALL_ACCESS_,
+ static_cast<::boost::detail::winapi::BOOL_>(0),
+ pid);
+
+ if (h == nullptr)
+ throw_last_error("OpenProcess() failed");
+ proc_info.hProcess = h;
+ proc_info.dwProcessId = pid;
+ }
+
+ child_handle() = default;
+ ~child_handle()
+ {
+ ::boost::detail::winapi::CloseHandle(proc_info.hProcess);
+ ::boost::detail::winapi::CloseHandle(proc_info.hThread);
+ }
+ child_handle(const child_handle & c) = delete;
+ child_handle(child_handle && c) : proc_info(c.proc_info)
+ {
+ c.proc_info.hProcess = ::boost::detail::winapi::invalid_handle_value;
+ c.proc_info.hThread = ::boost::detail::winapi::invalid_handle_value;
+ }
+ child_handle &operator=(const child_handle & c) = delete;
+ child_handle &operator=(child_handle && c)
+ {
+ ::boost::detail::winapi::CloseHandle(proc_info.hProcess);
+ ::boost::detail::winapi::CloseHandle(proc_info.hThread);
+ proc_info = c.proc_info;
+ c.proc_info.hProcess = ::boost::detail::winapi::invalid_handle_value;
+ c.proc_info.hThread = ::boost::detail::winapi::invalid_handle_value;
+ return *this;
+ }
+
+ pid_t id() const
+ {
+ return static_cast<int>(proc_info.dwProcessId);
+ }
+
+ typedef ::boost::detail::winapi::HANDLE_ process_handle_t;
+ process_handle_t process_handle() const { return proc_info.hProcess; }
+
+ bool valid() const
+ {
+ return (proc_info.hProcess != nullptr) &&
+ (proc_info.hProcess != ::boost::detail::winapi::INVALID_HANDLE_VALUE_);
+ }
+ bool in_group() const
+ {
+ ::boost::detail::winapi::BOOL_ value;
+ if (!::boost::detail::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
+ throw_last_error("IsProcessinJob Failed");
+ return value!=0;
+ }
+ bool in_group(std::error_code &ec) const noexcept
+ {
+ ::boost::detail::winapi::BOOL_ value;
+ if (!::boost::detail::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
+ ec = get_last_error();
+ return value!=0;
+ }
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/close_in.hpp b/boost/process/detail/windows/close_in.hpp
new file mode 100644
index 0000000000..5100564b4c
--- /dev/null
+++ b/boost/process/detail/windows/close_in.hpp
@@ -0,0 +1,31 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_IN_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_IN_HPP
+
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/process/detail/handler_base.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+struct close_in : public ::boost::process::detail::handler_base
+{
+ template <class WindowsExecutor>
+ void on_setup(WindowsExecutor &e) const
+ {
+ e.startup_info.hStdInput = boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
+ }
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/close_out.hpp b/boost/process/detail/windows/close_out.hpp
new file mode 100644
index 0000000000..dc3de412fc
--- /dev/null
+++ b/boost/process/detail/windows/close_out.hpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_OUT_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_OUT_HPP
+
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/process/detail/handler_base.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+template<int p1, int p2>
+struct close_out : public ::boost::process::detail::handler_base
+{
+ template <class WindowsExecutor>
+ inline void on_setup(WindowsExecutor &e) const;
+};
+
+template<>
+template<typename WindowsExecutor>
+void close_out<1,-1>::on_setup(WindowsExecutor &e) const
+{
+ e.startup_info.hStdOutput = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+}
+
+template<>
+template<typename WindowsExecutor>
+void close_out<2,-1>::on_setup(WindowsExecutor &e) const
+{
+ e.startup_info.hStdError = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+}
+
+template<>
+template<typename WindowsExecutor>
+void close_out<1,2>::on_setup(WindowsExecutor &e) const
+{
+ e.startup_info.hStdOutput = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ e.startup_info.hStdError = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/cmd.hpp b/boost/process/detail/windows/cmd.hpp
new file mode 100644
index 0000000000..c76c08a546
--- /dev/null
+++ b/boost/process/detail/windows/cmd.hpp
@@ -0,0 +1,49 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_WINDOWS_CMD_HPP_
+#define BOOST_PROCESS_WINDOWS_CMD_HPP_
+
+#include <string>
+
+namespace boost
+{
+namespace process
+{
+namespace detail
+{
+namespace windows
+{
+
+template<typename CharType>
+struct cmd_setter_ : ::boost::process::detail::handler_base
+{
+ typedef CharType value_type;
+ typedef std::basic_string<value_type> string_type;
+
+ cmd_setter_(string_type && cmd_line) : _cmd_line(std::move(cmd_line)) {}
+ cmd_setter_(const string_type & cmd_line) : _cmd_line(cmd_line) {}
+ template <class Executor>
+ void on_setup(Executor& exec)
+ {
+ exec.cmd_line = _cmd_line.c_str();
+ }
+ const string_type & str() const {return _cmd_line;}
+
+private:
+ string_type _cmd_line;
+};
+
+}
+
+
+}
+}
+}
+
+
+
+#endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ARGS_HPP_ */
diff --git a/boost/process/detail/windows/compare_handles.hpp b/boost/process/detail/windows/compare_handles.hpp
new file mode 100644
index 0000000000..1eafd43209
--- /dev/null
+++ b/boost/process/detail/windows/compare_handles.hpp
@@ -0,0 +1,41 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_COMPARE_HANDLES_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_COMPARE_HANDLES_HPP_
+
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/detail/winapi/file_management.hpp>
+#include <boost/process/detail/config.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+inline bool compare_handles(boost::detail::winapi::HANDLE_ lhs, boost::detail::winapi::HANDLE_ rhs)
+{
+ if ( (lhs == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ || (rhs == ::boost::detail::winapi::INVALID_HANDLE_VALUE_))
+ return false;
+
+ if (lhs == rhs)
+ return true;
+
+ ::boost::detail::winapi::BY_HANDLE_FILE_INFORMATION_ lhs_info{0,{0,0},{0,0},{0,0},0,0,0,0,0,0};
+ ::boost::detail::winapi::BY_HANDLE_FILE_INFORMATION_ rhs_info{0,{0,0},{0,0},{0,0},0,0,0,0,0,0};
+
+ if (!::boost::detail::winapi::GetFileInformationByHandle(lhs, &lhs_info))
+ ::boost::process::detail::throw_last_error("GetFileInformationByHandle");
+
+ if (!::boost::detail::winapi::GetFileInformationByHandle(rhs, &rhs_info))
+ ::boost::process::detail::throw_last_error("GetFileInformationByHandle");
+
+ return (lhs_info.nFileIndexHigh == rhs_info.nFileIndexHigh)
+ && (lhs_info.nFileIndexLow == rhs_info.nFileIndexLow);
+}
+
+}}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_COMPARE_HANDLES_HPP_ */
diff --git a/boost/process/detail/windows/env_init.hpp b/boost/process/detail/windows/env_init.hpp
new file mode 100644
index 0000000000..036a29809f
--- /dev/null
+++ b/boost/process/detail/windows/env_init.hpp
@@ -0,0 +1,54 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_ENV_INIT_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_ENV_INIT_HPP_
+
+#include <boost/detail/winapi/error_codes.hpp>
+#include <boost/detail/winapi/process.hpp>
+
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/environment.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+template<typename Char>
+struct env_init : public ::boost::process::detail::handler_base
+{
+ boost::process::basic_environment<Char> env;
+
+ env_init(boost::process::basic_environment<Char> && env) : env(std::move(env)) {};
+ env_init(const boost::process::basic_environment<Char> & env) : env(env) {};
+
+ constexpr static ::boost::detail::winapi::DWORD_ creation_flag(char) {return 0u;}
+ constexpr static ::boost::detail::winapi::DWORD_ creation_flag(wchar_t)
+ {
+ return ::boost::detail::winapi::CREATE_UNICODE_ENVIRONMENT_;
+ }
+
+ template <class WindowsExecutor>
+ void on_setup(WindowsExecutor &exec) const
+ {
+ auto e = env.native_handle();
+ if (*e == null_char<char>())
+ {
+ exec.set_error(std::error_code(::boost::detail::winapi::ERROR_BAD_ENVIRONMENT_, std::system_category()),
+ "Empty Environment");
+ }
+
+ exec.env = e;
+ exec.creation_flags |= creation_flag(Char());
+ }
+
+};
+
+}}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_INIT_HPP_ */
diff --git a/boost/process/detail/windows/environment.hpp b/boost/process/detail/windows/environment.hpp
new file mode 100644
index 0000000000..b73da1bd42
--- /dev/null
+++ b/boost/process/detail/windows/environment.hpp
@@ -0,0 +1,356 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <boost/detail/winapi/error_codes.hpp>
+#include <boost/detail/winapi/environment.hpp>
+#include <boost/process/detail/config.hpp>
+#include <boost/detail/winapi/get_current_process.hpp>
+#include <boost/detail/winapi/get_current_process_id.hpp>
+#include <algorithm>
+#include <boost/process/locale.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+template<typename Char>
+class native_environment_impl
+{
+ static void _deleter(Char* p) {boost::detail::winapi::free_environment_strings(p);};
+ std::unique_ptr<Char[], void(*)(Char*)> _buf{boost::detail::winapi::get_environment_strings<Char>(), &native_environment_impl::_deleter};
+ static inline std::vector<Char*> _load_var(Char* p);
+ std::vector<Char*> _env_arr{_load_var(_buf.get())};
+public:
+ using char_type = Char;
+ using pointer_type = const char_type*;
+ using string_type = std::basic_string<char_type>;
+ using native_handle_type = pointer_type;
+ void reload()
+ {
+ _buf.reset(boost::detail::winapi::get_environment_strings<Char>());
+ _env_arr = _load_var(_buf.get());
+ _env_impl = &*_env_arr.begin();
+ }
+
+ string_type get(const pointer_type id);
+ void set(const pointer_type id, const pointer_type value);
+ void reset(const pointer_type id);
+
+ string_type get(const string_type & id) {return get(id.c_str());}
+ void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
+ void reset(const string_type & id) {reset(id.c_str());}
+
+ native_environment_impl() = default;
+ native_environment_impl(const native_environment_impl& ) = delete;
+ native_environment_impl(native_environment_impl && ) = default;
+ native_environment_impl & operator=(const native_environment_impl& ) = delete;
+ native_environment_impl & operator=(native_environment_impl && ) = default;
+ Char ** _env_impl = &*_env_arr.begin();
+
+ native_handle_type native_handle() const {return _buf.get();}
+};
+
+template<typename Char>
+inline auto native_environment_impl<Char>::get(const pointer_type id) -> string_type
+{
+ Char buf[4096];
+ auto size = boost::detail::winapi::get_environment_variable(id, buf, sizeof(buf));
+ if (size == 0) //failed
+ {
+ auto err = ::boost::detail::winapi::GetLastError();
+ if (err == ::boost::detail::winapi::ERROR_ENVVAR_NOT_FOUND_)//well, then we consider that an empty value
+ return "";
+ else
+ throw process_error(std::error_code(err, std::system_category()),
+ "GetEnvironmentVariable() failed");
+ }
+
+ if (size == sizeof(buf)) //the return size gives the size without the null, so I know this went wrong
+ {
+ /*limit defined here https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx
+ * but I used 32768 so it is a multiple of 4096.
+ */
+ constexpr static std::size_t max_size = 32768;
+ //Handle variables longer then buf.
+ std::size_t buf_size = sizeof(buf);
+ while (buf_size <= max_size)
+ {
+ std::vector<Char> buf(buf_size);
+ auto size = boost::detail::winapi::get_environment_variable(id, buf.data(), buf.size());
+
+ if (size == buf_size) //buffer to small
+ buf_size *= 2;
+ else if (size == 0)
+ ::boost::process::detail::throw_last_error("GetEnvironmentVariable() failed");
+ else
+ return std::basic_string<Char>(
+ buf.data(), buf.data()+ size + 1);
+
+ }
+
+ }
+ return std::basic_string<Char>(buf, buf+size+1);
+}
+
+template<typename Char>
+inline void native_environment_impl<Char>::set(const pointer_type id, const pointer_type value)
+{
+ boost::detail::winapi::set_environment_variable(id, value);
+}
+
+template<typename Char>
+inline void native_environment_impl<Char>::reset(const pointer_type id)
+{
+ boost::detail::winapi::set_environment_variable(id, nullptr);
+}
+
+template<typename Char>
+std::vector<Char*> native_environment_impl<Char>::_load_var(Char* p)
+{
+ std::vector<Char*> ret;
+ if (*p != null_char<Char>())
+ {
+ ret.push_back(p);
+ while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
+ {
+ if (*p==null_char<Char>())
+ {
+ p++;
+ ret.push_back(p);
+ }
+ else
+ p++;
+ }
+ }
+ p++;
+ ret.push_back(nullptr);
+
+ return ret;
+}
+
+
+template<typename Char>
+struct basic_environment_impl
+{
+ std::vector<Char> _data = {null_char<Char>()};
+ static std::vector<Char*> _load_var(Char* p);
+ std::vector<Char*> _env_arr{_load_var(_data.data())};
+public:
+ using char_type = Char;
+ using pointer_type = const char_type*;
+ using string_type = std::basic_string<char_type>;
+ using native_handle_type = pointer_type;
+
+ std::size_t size() const { return _data.size();}
+
+ void reload()
+ {
+ _env_arr = _load_var(_data.data());
+ _env_impl = _env_arr.data();
+ }
+
+ string_type get(const pointer_type id) {return get(string_type(id));}
+ void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
+ void reset(const pointer_type id) {reset(string_type(id));}
+
+ string_type get(const string_type & id);
+ void set(const string_type & id, const string_type & value);
+ void reset(const string_type & id);
+
+ inline basic_environment_impl(const native_environment_impl<Char> & nei);
+ basic_environment_impl() = default;
+ basic_environment_impl(const basic_environment_impl& rhs)
+ : _data(rhs._data)
+ {
+ }
+ basic_environment_impl(basic_environment_impl && rhs)
+ : _data(std::move(rhs._data)),
+ _env_arr(std::move(rhs._env_arr)),
+ _env_impl(_env_arr.data())
+ {
+ }
+ basic_environment_impl &operator=(basic_environment_impl && rhs)
+ {
+ _data = std::move(rhs._data);
+ //reload();
+ _env_arr = std::move(rhs._env_arr);
+ _env_impl = _env_arr.data();
+
+ return *this;
+ }
+ basic_environment_impl & operator=(const basic_environment_impl& rhs)
+ {
+ _data = rhs._data;
+ reload();
+ return *this;
+ }
+
+ template<typename CharR>
+ explicit inline basic_environment_impl(
+ const basic_environment_impl<CharR>& rhs,
+ const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
+ : _data(::boost::process::detail::convert(rhs._data, cv))
+ {
+ }
+
+ template<typename CharR>
+ basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
+ {
+ _data = ::boost::process::detail::convert(rhs._data);
+ _env_arr = _load_var(&*_data.begin());
+ _env_impl = &*_env_arr.begin();
+ return *this;
+ }
+
+ Char ** _env_impl = &*_env_arr.begin();
+
+ native_handle_type native_handle() const {return &*_data.begin();}
+};
+
+
+template<typename Char>
+basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
+{
+ auto beg = nei.native_handle();
+ auto p = beg;
+ while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
+ p++;
+ p++; //pointing to the second nullchar
+ p++; //to get the pointer behing the second nullchar, so it's end.
+
+ this->_data.assign(beg, p);
+ this->reload();
+}
+
+
+template<typename Char>
+inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
+{
+
+ if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign<Char>()))
+ return string_type(_data.data()); //null-char is handled by the string.
+
+ std::vector<Char> seq = {'\0'}; //using a vector, because strings might cause problems with nullchars
+ seq.insert(seq.end(), id.begin(), id.end());
+ seq.push_back('=');
+
+ auto itr = std::search(_data.begin(), _data.end(), seq.begin(), seq.end());
+
+ if (itr == _data.end()) //not found
+ return "";
+
+ itr += seq.size(); //advance to the value behind the '='; the std::string will take care of finding the null-char.
+
+ return string_type(&*itr);
+}
+
+template<typename Char>
+inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
+{
+ reset(id);
+
+ std::vector<Char> insertion;
+
+ insertion.insert(insertion.end(), id.begin(), id.end());
+ insertion.push_back('=');
+ insertion.insert(insertion.end(), value.begin(), value.end());
+ insertion.push_back('\0');
+
+ _data.insert(_data.end() -1, insertion.begin(), insertion.end());
+
+ reload();
+}
+
+template<typename Char>
+inline void basic_environment_impl<Char>::reset(const string_type &id)
+{
+ //ok, we need to check the size of data first
+ if (id.size() >= _data.size()) //ok, so it's impossible id is in there.
+ return;
+
+ //check if it's the first one, spares us the search.
+ if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign<Char>()))
+ {
+ auto beg = _data.begin();
+ auto end = beg;
+
+ while (*end != '\0')
+ end++;
+
+ end++; //to point behind the last null-char
+
+ _data.erase(beg, end); //and remove the thingy
+
+ }
+
+ std::vector<Char> seq = {'\0'}; //using a vector, because strings might cause problems with nullchars
+ seq.insert(seq.end(), id.begin(), id.end());
+ seq.push_back('=');
+
+ auto itr = std::search(_data.begin(), _data.end(), seq.begin(), seq.end());
+
+ if (itr == _data.end())
+ return;//nothing to return if it's empty anyway...
+
+ auto end = itr;
+
+ while (*end != '\0')
+ end++;
+
+ end ++; //to point behind the last null-char
+
+ _data.erase(itr, end);//and remove it
+ reload();
+
+
+}
+
+template<typename Char>
+std::vector<Char*> basic_environment_impl<Char>::_load_var(Char* p)
+{
+ std::vector<Char*> ret;
+ if (*p != null_char<Char>())
+ {
+ ret.push_back(p);
+ while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
+ {
+ if (*p==null_char<Char>())
+ {
+ p++;
+ ret.push_back(p);
+ }
+ else
+ p++;
+ }
+ }
+ p++;
+ ret.push_back(nullptr);
+ return ret;
+}
+
+
+template<typename T> constexpr T env_seperator();
+template<> constexpr char env_seperator() {return ';'; }
+template<> constexpr wchar_t env_seperator() {return L';'; }
+
+inline int get_id() {return boost::detail::winapi::GetCurrentProcessId();}
+inline void* native_handle() {return boost::detail::winapi::GetCurrentProcess(); }
+
+typedef void* native_handle_t;
+
+}
+
+}
+}
+}
+
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */
diff --git a/boost/process/detail/windows/executor.hpp b/boost/process/detail/windows/executor.hpp
new file mode 100644
index 0000000000..30b1e46369
--- /dev/null
+++ b/boost/process/detail/windows/executor.hpp
@@ -0,0 +1,259 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_EXECUTOR_HPP
+#define BOOST_PROCESS_WINDOWS_EXECUTOR_HPP
+
+#include <boost/process/detail/child_decl.hpp>
+#include <boost/process/detail/windows/is_running.hpp>
+#include <boost/process/detail/traits.hpp>
+#include <boost/process/error.hpp>
+#include <boost/fusion/algorithm/iteration/for_each.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/detail/winapi/process.hpp>
+#include <boost/none.hpp>
+#include <system_error>
+#include <memory>
+#include <atomic>
+#include <cstring>
+
+namespace boost { namespace process {
+
+namespace detail { namespace windows {
+
+template<typename CharType> struct startup_info;
+#if !defined( BOOST_NO_ANSI_APIS )
+
+template<> struct startup_info<char>
+{
+ typedef ::boost::detail::winapi::STARTUPINFOA_ type;
+};
+#endif
+
+template<> struct startup_info<wchar_t>
+{
+ typedef ::boost::detail::winapi::STARTUPINFOW_ type;
+};
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+
+template<typename CharType> struct startup_info_ex;
+
+#if !defined( BOOST_NO_ANSI_APIS )
+template<> struct startup_info_ex<char>
+{
+ typedef ::boost::detail::winapi::STARTUPINFOEXA_ type;
+};
+#endif
+
+template<> struct startup_info_ex<wchar_t>
+{
+ typedef ::boost::detail::winapi::STARTUPINFOEXW_ type;
+};
+
+
+#endif
+
+#if ( BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 )
+
+template<typename CharT>
+struct startup_info_impl
+{
+ ::boost::detail::winapi::DWORD_ creation_flags = 0;
+
+ typedef typename startup_info_ex<CharT>::type startup_info_ex_t;
+ typedef typename startup_info<CharT>::type startup_info_t;
+
+ startup_info_ex_t startup_info_ex
+ {startup_info_t {sizeof(startup_info_t), nullptr, nullptr, nullptr,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr,
+ ::boost::detail::winapi::invalid_handle_value,
+ ::boost::detail::winapi::invalid_handle_value,
+ ::boost::detail::winapi::invalid_handle_value},
+ nullptr
+ };
+ startup_info_t & startup_info = startup_info_ex.StartupInfo;
+
+ void set_startup_info_ex()
+ {
+ startup_info.cb = sizeof(startup_info_ex_t);
+ creation_flags = ::boost::detail::winapi::EXTENDED_STARTUPINFO_PRESENT_;
+ }
+};
+
+
+#else
+
+template<typename CharT>
+struct startup_info_impl
+{
+ typedef typename startup_info<CharT>::type startup_info_t;
+
+ ::boost::detail::winapi::DWORD_ creation_flags = 0;
+ startup_info_t startup_info
+ {sizeof(startup_info_t), nullptr, nullptr, nullptr,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr,
+ ::boost::detail::winapi::invalid_handle_value,
+ ::boost::detail::winapi::invalid_handle_value,
+ ::boost::detail::winapi::invalid_handle_value};
+};
+#endif
+
+
+
+template<typename Char, typename Sequence>
+class executor : public startup_info_impl<Char>
+{
+
+ void internal_error_handle(const std::error_code &, const char*, boost::mpl::false_, boost::mpl::true_) {}
+ void internal_error_handle(const std::error_code &, const char*, boost::mpl::true_, boost::mpl::true_) {}
+
+ void internal_error_handle(const std::error_code &ec, const char*, boost::mpl::true_, boost::mpl::false_ )
+ {
+ this->_ec = ec;
+ }
+ void internal_error_handle(const std::error_code &ec, const char* msg, boost::mpl::false_, boost::mpl::false_ )
+ {
+ throw process_error(ec, msg);
+ }
+
+ struct on_setup_t
+ {
+ executor & exec;
+ on_setup_t(executor & exec) : exec(exec) {};
+ template<typename T>
+ void operator()(T & t) const
+ {
+ if (!exec.error())
+ t.on_setup(exec);
+ }
+ };
+
+ struct on_error_t
+ {
+ executor & exec;
+ const std::error_code & error;
+ on_error_t(executor & exec, const std::error_code & error) : exec(exec), error(error) {};
+ template<typename T>
+ void operator()(T & t) const
+ {
+ t.on_error(exec, error);
+ }
+ };
+
+ struct on_success_t
+ {
+ executor & exec;
+ on_success_t(executor & exec) : exec(exec) {};
+ template<typename T>
+ void operator()(T & t) const
+ {
+ if (!exec.error())
+ t.on_success(exec);
+ }
+ };
+
+ typedef typename ::boost::process::detail::has_error_handler<Sequence>::type has_error_handler;
+ typedef typename ::boost::process::detail::has_ignore_error <Sequence>::type has_ignore_error;
+
+ std::error_code _ec{0, std::system_category()};
+
+public:
+
+ std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active);
+
+ executor(Sequence & seq) : seq(seq)
+ {
+ }
+
+ child operator()()
+ {
+ on_setup_t on_setup_fn(*this);
+ boost::fusion::for_each(seq, on_setup_fn);
+
+ if (_ec)
+ {
+ on_error_t on_error_fn(*this, _ec);
+ boost::fusion::for_each(seq, on_error_fn);
+ return child();
+ }
+
+ //NOTE: The non-cast cmd-line string can only be modified by the wchar_t variant which is currently disabled.
+ int err_code = ::boost::detail::winapi::create_process(
+ exe, // LPCSTR_ lpApplicationName,
+ const_cast<Char*>(cmd_line), // LPSTR_ lpCommandLine,
+ proc_attrs, // LPSECURITY_ATTRIBUTES_ lpProcessAttributes,
+ thread_attrs, // LPSECURITY_ATTRIBUTES_ lpThreadAttributes,
+ inherit_handles, // INT_ bInheritHandles,
+ this->creation_flags, // DWORD_ dwCreationFlags,
+ reinterpret_cast<void*>(const_cast<Char*>(env)), // LPVOID_ lpEnvironment,
+ work_dir, // LPCSTR_ lpCurrentDirectory,
+ &this->startup_info, // LPSTARTUPINFOA_ lpStartupInfo,
+ &proc_info); // LPPROCESS_INFORMATION_ lpProcessInformation)
+
+ child c{child_handle(proc_info), exit_status};
+
+ if (err_code != 0)
+ {
+ _ec.clear();
+ on_success_t on_success_fn(*this);
+ boost::fusion::for_each(seq, on_success_fn);
+ }
+ else
+ set_error(::boost::process::detail::get_last_error(),
+ " CreateProcess failed");
+
+ if ( _ec)
+ {
+ on_error_t on_err(*this, _ec);
+ boost::fusion::for_each(seq, on_err);
+ return child();
+ }
+ else
+ return c;
+
+ }
+
+ void set_error(const std::error_code & ec, const char* msg = "Unknown Error.")
+ {
+ internal_error_handle(ec, msg, has_error_handler(), has_ignore_error());
+ }
+ void set_error(const std::error_code & ec, const std::string msg = "Unknown Error.")
+ {
+ internal_error_handle(ec, msg.c_str(), has_error_handler(), has_ignore_error());
+ }
+
+ const std::error_code& error() const {return _ec;}
+
+ ::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ proc_attrs = nullptr;
+ ::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ thread_attrs = nullptr;
+ ::boost::detail::winapi::BOOL_ inherit_handles = false;
+ const Char * work_dir = nullptr;
+ const Char * cmd_line = nullptr;
+ const Char * exe = nullptr;
+ const Char * env = nullptr;
+
+
+ Sequence & seq;
+ ::boost::detail::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
+};
+
+
+
+template<typename Char, typename Tup>
+executor<Char, Tup> make_executor(Tup & tup)
+{
+ return executor<Char, Tup>(tup);
+}
+
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/file_descriptor.hpp b/boost/process/detail/windows/file_descriptor.hpp
new file mode 100644
index 0000000000..337e634781
--- /dev/null
+++ b/boost/process/detail/windows/file_descriptor.hpp
@@ -0,0 +1,104 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/detail/winapi/file_management.hpp>
+#include <string>
+#include <boost/filesystem/path.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+struct file_descriptor
+{
+ enum mode_t
+ {
+ read = 1,
+ write = 2,
+ read_write = 3
+ };
+ static ::boost::detail::winapi::DWORD_ desired_access(mode_t mode)
+ {
+ switch(mode)
+ {
+ case read:
+ return ::boost::detail::winapi::GENERIC_READ_;
+ case write:
+ return ::boost::detail::winapi::GENERIC_WRITE_;
+ case read_write:
+ return ::boost::detail::winapi::GENERIC_READ_
+ | ::boost::detail::winapi::GENERIC_WRITE_;
+ default:
+ return 0u;
+ }
+ }
+
+ file_descriptor() = default;
+ file_descriptor(const boost::filesystem::path& p, mode_t mode = read_write)
+ : file_descriptor(p.native(), mode)
+ {
+ }
+
+ file_descriptor(const std::string & path , mode_t mode = read_write)
+ : file_descriptor(path.c_str(), mode) {}
+ file_descriptor(const std::wstring & path, mode_t mode = read_write)
+ : file_descriptor(path.c_str(), mode) {}
+
+ file_descriptor(const char* path, mode_t mode = read_write)
+ : _handle(
+ ::boost::detail::winapi::create_file(
+ path,
+ desired_access(mode),
+ ::boost::detail::winapi::FILE_SHARE_READ_ |
+ ::boost::detail::winapi::FILE_SHARE_WRITE_,
+ nullptr,
+ ::boost::detail::winapi::OPEN_ALWAYS_,
+
+ ::boost::detail::winapi::FILE_ATTRIBUTE_NORMAL_,
+ nullptr
+ ))
+ {
+
+ }
+ file_descriptor(const wchar_t * path, mode_t mode = read_write)
+ : _handle(
+ ::boost::detail::winapi::create_file(
+ path,
+ desired_access(mode),
+ ::boost::detail::winapi::FILE_SHARE_READ_ |
+ ::boost::detail::winapi::FILE_SHARE_WRITE_,
+ nullptr,
+ ::boost::detail::winapi::OPEN_ALWAYS_,
+
+ ::boost::detail::winapi::FILE_ATTRIBUTE_NORMAL_,
+ nullptr
+ ))
+{
+
+}
+ file_descriptor(const file_descriptor & ) = delete;
+ file_descriptor(file_descriptor && ) = default;
+
+ file_descriptor& operator=(const file_descriptor & ) = delete;
+ file_descriptor& operator=(file_descriptor && ) = default;
+
+ ~file_descriptor()
+ {
+ if (_handle != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
+ ::boost::detail::winapi::CloseHandle(_handle);
+ }
+
+ ::boost::detail::winapi::HANDLE_ handle() const { return _handle;}
+
+private:
+ ::boost::detail::winapi::HANDLE_ _handle = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+};
+
+}}}}
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_ */
diff --git a/boost/process/detail/windows/file_in.hpp b/boost/process/detail/windows/file_in.hpp
new file mode 100644
index 0000000000..b092d278c2
--- /dev/null
+++ b/boost/process/detail/windows/file_in.hpp
@@ -0,0 +1,44 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_FILE_IN_HPP
+#define BOOST_PROCESS_DETAIL_WINDOWS_FILE_IN_HPP
+
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/windows/file_descriptor.hpp>
+#include <io.h>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+struct file_in : public ::boost::process::detail::handler_base
+{
+ file_descriptor file;
+ ::boost::detail::winapi::HANDLE_ handle = file.handle();
+
+ template<typename T>
+ file_in(T&& t) : file(std::forward<T>(t), file_descriptor::read) {}
+ file_in(FILE * f) : handle(reinterpret_cast<::boost::detail::winapi::HANDLE_>(_get_osfhandle(_fileno(f)))) {}
+
+ template <class WindowsExecutor>
+ void on_setup(WindowsExecutor &e) const
+ {
+ boost::detail::winapi::SetHandleInformation(handle,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+ e.startup_info.hStdInput = handle;
+ e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+ }
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/file_out.hpp b/boost/process/detail/windows/file_out.hpp
new file mode 100644
index 0000000000..2e2cc198cf
--- /dev/null
+++ b/boost/process/detail/windows/file_out.hpp
@@ -0,0 +1,77 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_FILE_OUT_HPP
+#define BOOST_PROCESS_DETAIL_WINDOWS_FILE_OUT_HPP
+
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/detail/winapi/handle_info.hpp>
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/windows/file_descriptor.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+template<int p1, int p2>
+struct file_out : public ::boost::process::detail::handler_base
+{
+ file_descriptor file;
+ ::boost::detail::winapi::HANDLE_ handle = file.handle();
+
+ template<typename T>
+ file_out(T&& t) : file(std::forward<T>(t), file_descriptor::write) {}
+ file_out(FILE * f) : handle(reinterpret_cast<void*>(_get_osfhandle(_fileno(f)))) {}
+
+ template <typename WindowsExecutor>
+ inline void on_setup(WindowsExecutor &e) const;
+};
+
+template<>
+template<typename WindowsExecutor>
+void file_out<1,-1>::on_setup(WindowsExecutor &e) const
+{
+ boost::detail::winapi::SetHandleInformation(handle,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ e.startup_info.hStdOutput = handle;
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+}
+
+template<>
+template<typename WindowsExecutor>
+void file_out<2,-1>::on_setup(WindowsExecutor &e) const
+{
+ boost::detail::winapi::SetHandleInformation(handle,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ e.startup_info.hStdError = handle;
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+}
+
+template<>
+template<typename WindowsExecutor>
+void file_out<1,2>::on_setup(WindowsExecutor &e) const
+{
+ boost::detail::winapi::SetHandleInformation(handle,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ e.startup_info.hStdOutput = handle;
+ e.startup_info.hStdError = handle;
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/group_handle.hpp b/boost/process/detail/windows/group_handle.hpp
new file mode 100644
index 0000000000..e289263cad
--- /dev/null
+++ b/boost/process/detail/windows/group_handle.hpp
@@ -0,0 +1,191 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_
+
+#include <boost/process/detail/windows/handler.hpp>
+#include <boost/detail/winapi/jobs.hpp>
+#include <boost/process/detail/windows/child_handle.hpp>
+#include <boost/process/detail/windows/job_workaround.hpp>
+#include <system_error>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+inline bool break_away_enabled(::boost::detail::winapi::HANDLE_ h)
+{
+ workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
+
+ if (!workaround::query_information_job_object(
+ h,
+ workaround::JobObjectExtendedLimitInformation_,
+ static_cast<void*>(&info),
+ sizeof(info),
+ nullptr))
+ throw_last_error("QueryInformationJobObject() failed");
+
+ return (info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0;
+}
+
+inline void enable_break_away(::boost::detail::winapi::HANDLE_ h)
+{
+ workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
+
+ if (!workaround::query_information_job_object(
+ h,
+ workaround::JobObjectExtendedLimitInformation_,
+ static_cast<void*>(&info),
+ sizeof(info),
+ nullptr))
+ throw_last_error("QueryInformationJobObject() failed");
+
+ if ((info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0)
+ return;
+
+ info.BasicLimitInformation.LimitFlags |= workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_;
+
+ if (!workaround::set_information_job_object(
+ h,
+ workaround::JobObjectExtendedLimitInformation_,
+ static_cast<void*>(&info),
+ sizeof(info)))
+ throw_last_error("SetInformationJobObject() failed");
+}
+
+inline void enable_break_away(::boost::detail::winapi::HANDLE_ h, std::error_code & ec)
+{
+ workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
+
+
+ if (!workaround::query_information_job_object(
+ h,
+ workaround::JobObjectExtendedLimitInformation_,
+ static_cast<void*>(&info),
+ sizeof(info),
+ nullptr))
+ {
+ ec = get_last_error();
+ return;
+ }
+
+ if ((info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0)
+ return;
+
+ info.BasicLimitInformation.LimitFlags |= workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_;
+
+ if (!workaround::set_information_job_object(
+ h,
+ workaround::JobObjectExtendedLimitInformation_,
+ static_cast<void*>(&info),
+ sizeof(info)))
+ {
+ ec = get_last_error();
+ return;
+ }
+
+
+}
+
+
+struct group_handle
+{
+ ::boost::detail::winapi::HANDLE_ _job_object;
+
+ typedef ::boost::detail::winapi::HANDLE_ handle_t;
+ handle_t handle() const { return _job_object; }
+
+ explicit group_handle(handle_t h) :
+ _job_object(h)
+ {
+ enable_break_away(_job_object);
+ }
+
+
+ group_handle() : group_handle(::boost::detail::winapi::CreateJobObjectA(nullptr, nullptr))
+ {
+
+ }
+ ~group_handle()
+ {
+ ::boost::detail::winapi::CloseHandle(_job_object);
+ }
+ group_handle(const group_handle & c) = delete;
+ group_handle(group_handle && c) : _job_object(c._job_object)
+ {
+ c._job_object = ::boost::detail::winapi::invalid_handle_value;
+ }
+ group_handle &operator=(const group_handle & c) = delete;
+ group_handle &operator=(group_handle && c)
+ {
+
+ ::boost::detail::winapi::CloseHandle(_job_object);
+ _job_object = c._job_object;
+ c._job_object = ::boost::detail::winapi::invalid_handle_value;
+ return *this;
+ }
+
+ void add(handle_t proc)
+ {
+ if (!::boost::detail::winapi::AssignProcessToJobObject(_job_object, proc))
+ throw_last_error();
+ }
+ void add(handle_t proc, std::error_code & ec) noexcept
+ {
+ if (!::boost::detail::winapi::AssignProcessToJobObject(_job_object, proc))
+ ec = get_last_error();
+ }
+
+ bool has(handle_t proc)
+ {
+ ::boost::detail::winapi::BOOL_ is;
+ if (!::boost::detail::winapi::IsProcessInJob(proc, _job_object, &is))
+ throw_last_error();
+
+ return is!=0;
+ }
+ bool has(handle_t proc, std::error_code & ec) noexcept
+ {
+ ::boost::detail::winapi::BOOL_ is;
+ if (!::boost::detail::winapi::IsProcessInJob(proc, _job_object, &is))
+ ec = get_last_error();
+ return is!=0;
+ }
+
+ bool valid() const
+ {
+ return _job_object != nullptr;
+ }
+
+};
+
+inline void terminate(const group_handle &p)
+{
+ if (!::boost::detail::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
+ boost::process::detail::throw_last_error("TerminateJobObject() failed");
+}
+
+inline void terminate(const group_handle &p, std::error_code &ec) noexcept
+{
+ if (!::boost::detail::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
+ ec = boost::process::detail::get_last_error();
+ else
+ ec.clear();
+}
+
+inline bool in_group()
+{
+ ::boost::detail::winapi::BOOL_ res;
+ if (!::boost::detail::winapi::IsProcessInJob(boost::detail::winapi::GetCurrentProcess(), nullptr, &res))
+ throw_last_error("IsProcessInJob failed");
+
+ return res!=0;
+}
+
+
+
+}}}}
+
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_ */
diff --git a/boost/process/detail/windows/group_ref.hpp b/boost/process/detail/windows/group_ref.hpp
new file mode 100644
index 0000000000..1f62c4dcb0
--- /dev/null
+++ b/boost/process/detail/windows/group_ref.hpp
@@ -0,0 +1,51 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_GROUP_REF_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_GROUP_REF_HPP_
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/windows/group_handle.hpp>
+#include <boost/detail/winapi/process.hpp>
+#include <boost/process/detail/windows/handler.hpp>
+
+namespace boost { namespace process {
+
+namespace detail { namespace windows {
+
+
+
+struct group_ref : handler_base_ext
+{
+ ::boost::detail::winapi::HANDLE_ handle;
+
+ explicit group_ref(group_handle &g) :
+ handle(g.handle())
+ {}
+
+ template <class Executor>
+ void on_setup(Executor& exec) const
+ {
+ //I can only enable this if the current process supports breakaways.
+ if (in_group() && break_away_enabled(nullptr))
+ exec.creation_flags |= boost::detail::winapi::CREATE_BREAKAWAY_FROM_JOB_;
+ }
+
+
+ template <class Executor>
+ void on_success(Executor& exec) const
+ {
+ if (!::boost::detail::winapi::AssignProcessToJobObject(handle, exec.proc_info.hProcess))
+ exec.set_error(::boost::process::detail::get_last_error(),
+ "AssignProcessToJobObject() failed.");
+
+ }
+
+};
+
+}}}}
+
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_ */
diff --git a/boost/process/detail/windows/handler.hpp b/boost/process/detail/windows/handler.hpp
new file mode 100644
index 0000000000..f8ef89f016
--- /dev/null
+++ b/boost/process/detail/windows/handler.hpp
@@ -0,0 +1,20 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_HANDLER_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_HANDLER_HPP_
+
+#include <boost/process/detail/handler_base.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+//does not extend anything.
+struct handler_base_ext : handler_base {};
+
+}}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_HANDLER_HPP_ */
diff --git a/boost/process/detail/windows/io_service_ref.hpp b/boost/process/detail/windows/io_service_ref.hpp
new file mode 100644
index 0000000000..6b61c7ca2c
--- /dev/null
+++ b/boost/process/detail/windows/io_service_ref.hpp
@@ -0,0 +1,160 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_
+#define BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_
+
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/windows/async_handler.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/windows/object_handle.hpp>
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/handles.hpp>
+
+#include <boost/fusion/algorithm/iteration/for_each.hpp>
+#include <boost/fusion/algorithm/transformation/filter_if.hpp>
+#include <boost/fusion/algorithm/transformation/transform.hpp>
+#include <boost/fusion/view/transform_view.hpp>
+#include <boost/fusion/container/vector/convert.hpp>
+
+
+#include <functional>
+#include <type_traits>
+#include <memory>
+#include <atomic>
+#include <vector>
+
+#include <boost/type_index.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+template<typename Executor>
+struct on_exit_handler_transformer
+{
+ Executor & exec;
+ on_exit_handler_transformer(Executor & exec) : exec(exec) {}
+ template<typename Sig>
+ struct result;
+
+ template<typename T>
+ struct result<on_exit_handler_transformer<Executor>(T&)>
+ {
+ typedef typename T::on_exit_handler_t type;
+ };
+
+ template<typename T>
+ auto operator()(T& t) const -> typename T::on_exit_handler_t
+ {
+ return t.on_exit_handler(exec);
+ }
+};
+
+template<typename Executor>
+struct async_handler_collector
+{
+ Executor & exec;
+ std::vector<std::function<void(int, const std::error_code & ec)>> &handlers;
+
+
+ async_handler_collector(Executor & exec,
+ std::vector<std::function<void(int, const std::error_code & ec)>> &handlers)
+ : exec(exec), handlers(handlers) {}
+
+ template<typename T>
+ void operator()(T & t) const
+ {
+ handlers.push_back(t.on_exit_handler(exec));
+ }
+};
+
+//Also set's up waiting for the exit, so it can close async stuff.
+struct io_service_ref : boost::process::detail::handler_base
+{
+
+ io_service_ref(boost::asio::io_service & ios)
+ : ios(ios)
+ {
+ }
+ boost::asio::io_service &get() {return ios;};
+
+ template <class Executor>
+ void on_success(Executor& exec) const
+ {
+ auto asyncs = boost::fusion::filter_if<
+ is_async_handler<
+ typename std::remove_reference< boost::mpl::_ > ::type
+ >>(exec.seq);
+
+ //ok, check if there are actually any.
+ if (boost::fusion::empty(asyncs))
+ {
+ return;
+ }
+
+ ::boost::detail::winapi::PROCESS_INFORMATION_ & proc = exec.proc_info;
+ auto this_proc = ::boost::detail::winapi::GetCurrentProcess();
+
+ auto proc_in = proc.hProcess;;
+ ::boost::detail::winapi::HANDLE_ process_handle;
+
+ if (!::boost::detail::winapi::DuplicateHandle(
+ this_proc, proc_in, this_proc, &process_handle, 0,
+ static_cast<::boost::detail::winapi::BOOL_>(true),
+ ::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
+
+ exec.set_error(::boost::process::detail::get_last_error(),
+ "Duplicate Pipe Failed");
+
+
+ std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
+ funcs.reserve(boost::fusion::size(asyncs));
+ boost::fusion::for_each(asyncs, async_handler_collector<Executor>(exec, funcs));
+
+ wait_handler wh(std::move(funcs), ios, process_handle, exec.exit_status);
+
+ auto handle_p = wh.handle.get();
+ handle_p->async_wait(std::move(wh));
+ }
+
+
+ struct wait_handler
+ {
+ std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
+ std::unique_ptr<boost::asio::windows::object_handle> handle;
+ std::shared_ptr<std::atomic<int>> exit_status;
+ wait_handler(const wait_handler & ) = delete;
+ wait_handler(wait_handler && ) = default;
+ wait_handler(std::vector<std::function<void(int, const std::error_code & ec)>> && funcs,
+ boost::asio::io_service & ios, void * handle,
+ const std::shared_ptr<std::atomic<int>> &exit_status)
+ : funcs(std::move(funcs)),
+ handle(new boost::asio::windows::object_handle(ios, handle)),
+ exit_status(exit_status)
+ {
+
+ }
+ void operator()(const boost::system::error_code & ec_in)
+ {
+ std::error_code ec;
+ if (ec_in)
+ ec = std::error_code(ec_in.value(), std::system_category());
+
+ ::boost::detail::winapi::DWORD_ code;
+ ::boost::detail::winapi::GetExitCodeProcess(handle->native(), &code);
+ exit_status->store(code);
+
+ for (auto & func : funcs)
+ func(code, ec);
+ }
+
+ };
+
+private:
+ boost::asio::io_service &ios;
+};
+
+}}}}
+
+#endif /* BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_ */
diff --git a/boost/process/detail/windows/is_running.hpp b/boost/process/detail/windows/is_running.hpp
new file mode 100644
index 0000000000..66cc6837ae
--- /dev/null
+++ b/boost/process/detail/windows/is_running.hpp
@@ -0,0 +1,64 @@
+// Copyright (c) 2106 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_IS_RUNNING_HPP
+#define BOOST_PROCESS_WINDOWS_IS_RUNNING_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <system_error>
+#include <cstdlib>
+#include <boost/detail/winapi/process.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+constexpr static ::boost::detail::winapi::DWORD_ still_active = 259;
+
+
+struct child_handle;
+
+inline bool is_running(const child_handle &p, int & exit_code)
+{
+ ::boost::detail::winapi::DWORD_ code;
+ //single value, not needed in the winapi.
+ if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &code))
+ ::boost::process::detail::throw_last_error("GetExitCodeProcess() failed");
+
+ if (code == still_active)
+ return true;
+ else
+ {
+ exit_code = code;
+ return false;
+ }
+}
+
+inline bool is_running(const child_handle &p, int & exit_code, std::error_code &ec) noexcept
+{
+ ::boost::detail::winapi::DWORD_ code;
+ //single value, not needed in the winapi.
+ if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &code))
+ ec = ::boost::process::detail::get_last_error();
+ else
+ ec.clear();
+
+ if (code == still_active)
+ return true;
+ else
+ {
+ exit_code = code;
+ return false;
+ }
+}
+
+inline bool is_running(int code)
+{
+ return code == still_active;
+}
+
+inline int eval_exit_status(int in ) {return in;}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/job_workaround.hpp b/boost/process/detail/windows/job_workaround.hpp
new file mode 100644
index 0000000000..b915d0c088
--- /dev/null
+++ b/boost/process/detail/windows/job_workaround.hpp
@@ -0,0 +1,139 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_
+
+#include <boost/detail/winapi/config.hpp>
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/dll.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows { namespace workaround {
+
+//this import workaround is to keep it a header-only library. and enums cannot be imported from the winapi.
+
+extern "C"
+{
+
+typedef enum _JOBOBJECTINFOCLASS_ {
+ JobObjectBasicAccountingInformation_ = 1, JobObjectBasicLimitInformation_,
+ JobObjectBasicProcessIdList_, JobObjectBasicUIRestrictions_,
+ JobObjectSecurityLimitInformation_, JobObjectEndOfJobTimeInformation_,
+ JobObjectAssociateCompletionPortInformation_, JobObjectBasicAndIoAccountingInformation_,
+ JobObjectExtendedLimitInformation_, JobObjectJobSetInformation_,
+ JobObjectGroupInformation_,
+ JobObjectNotificationLimitInformation_,
+ JobObjectLimitViolationInformation_,
+ JobObjectGroupInformationEx_,
+ JobObjectCpuRateControlInformation_,
+ JobObjectCompletionFilter_,
+ JobObjectCompletionCounter_,
+ JobObjectReserved1Information_ = 18,
+ JobObjectReserved2Information_,
+ JobObjectReserved3Information_,
+ JobObjectReserved4Information_,
+ JobObjectReserved5Information_,
+ JobObjectReserved6Information_,
+ JobObjectReserved7Information_,
+ JobObjectReserved8Information_,
+ MaxJobObjectInfoClass_
+ } JOBOBJECTINFOCLASS_;
+
+typedef struct _JOBOBJECT_BASIC_LIMIT_INFORMATION_ {
+ ::boost::detail::winapi::LARGE_INTEGER_ PerProcessUserTimeLimit;
+ ::boost::detail::winapi::LARGE_INTEGER_ PerJobUserTimeLimit;
+ ::boost::detail::winapi::DWORD_ LimitFlags;
+ ::boost::detail::winapi::SIZE_T_ MinimumWorkingSetSize;
+ ::boost::detail::winapi::SIZE_T_ MaximumWorkingSetSize;
+ ::boost::detail::winapi::DWORD_ ActiveProcessLimit;
+ ::boost::detail::winapi::ULONG_PTR_ Affinity;
+ ::boost::detail::winapi::DWORD_ PriorityClass;
+ ::boost::detail::winapi::DWORD_ SchedulingClass;
+} JOBOBJECT_BASIC_LIMIT_INFORMATION_;
+
+
+typedef struct _IO_COUNTERS_ {
+ ::boost::detail::winapi::ULONGLONG_ ReadOperationCount;
+ ::boost::detail::winapi::ULONGLONG_ WriteOperationCount;
+ ::boost::detail::winapi::ULONGLONG_ OtherOperationCount;
+ ::boost::detail::winapi::ULONGLONG_ ReadTransferCount;
+ ::boost::detail::winapi::ULONGLONG_ WriteTransferCount;
+ ::boost::detail::winapi::ULONGLONG_ OtherTransferCount;
+} IO_COUNTERS_;
+
+
+typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ {
+ JOBOBJECT_BASIC_LIMIT_INFORMATION_ BasicLimitInformation;
+ IO_COUNTERS_ IoInfo;
+ ::boost::detail::winapi::SIZE_T_ ProcessMemoryLimit;
+ ::boost::detail::winapi::SIZE_T_ JobMemoryLimit;
+ ::boost::detail::winapi::SIZE_T_ PeakProcessMemoryUsed;
+ ::boost::detail::winapi::SIZE_T_ PeakJobMemoryUsed;
+} JOBOBJECT_EXTENDED_LIMIT_INFORMATION_;
+
+
+/*BOOL WINAPI QueryInformationJobObject(
+ _In_opt_ HANDLE hJob,
+ _In_ JOBOBJECTINFOCLASS JobObjectInfoClass,
+ _Out_ LPVOID lpJobObjectInfo,
+ _In_ DWORD cbJobObjectInfoLength,
+ _Out_opt_ LPDWORD lpReturnLength
+);
+ */
+typedef ::boost::detail::winapi::BOOL_ ( WINAPI *query_information_job_object_p)(
+ ::boost::detail::winapi::HANDLE_,
+ JOBOBJECTINFOCLASS_,
+ void *,
+ ::boost::detail::winapi::DWORD_,
+ ::boost::detail::winapi::DWORD_ *);
+
+
+inline ::boost::detail::winapi::BOOL_ WINAPI query_information_job_object(
+ ::boost::detail::winapi::HANDLE_ hJob,
+ JOBOBJECTINFOCLASS_ JobObjectInfoClass,
+ void * lpJobObjectInfo,
+ ::boost::detail::winapi::DWORD_ cbJobObjectInfoLength,
+ ::boost::detail::winapi::DWORD_ *lpReturnLength)
+{
+ static ::boost::detail::winapi::HMODULE_ h = ::boost::detail::winapi::get_module_handle("Kernel32.dll");
+ static query_information_job_object_p f = reinterpret_cast<query_information_job_object_p>(::boost::detail::winapi::get_proc_address(h, "QueryInformationJobObject"));
+
+ return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength, lpReturnLength);
+}
+
+/*BOOL WINAPI SetInformationJobObject(
+ _In_ HANDLE hJob,
+ _In_ JOBOBJECTINFOCLASS JobObjectInfoClass,
+ _In_ LPVOID lpJobObjectInfo,
+ _In_ DWORD cbJobObjectInfoLength
+);*/
+
+typedef ::boost::detail::winapi::BOOL_ ( WINAPI *set_information_job_object_p)(
+ ::boost::detail::winapi::HANDLE_,
+ JOBOBJECTINFOCLASS_,
+ void *,
+ ::boost::detail::winapi::DWORD_);
+
+}
+
+inline ::boost::detail::winapi::BOOL_ WINAPI set_information_job_object(
+ ::boost::detail::winapi::HANDLE_ hJob,
+ JOBOBJECTINFOCLASS_ JobObjectInfoClass,
+ void * lpJobObjectInfo,
+ ::boost::detail::winapi::DWORD_ cbJobObjectInfoLength)
+{
+ static ::boost::detail::winapi::HMODULE_ h = ::boost::detail::winapi::get_module_handle("Kernel32.dll");
+ static set_information_job_object_p f = reinterpret_cast<set_information_job_object_p>(::boost::detail::winapi::get_proc_address(h, "SetInformationJobObject"));
+
+ return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength);
+}
+
+constexpr static ::boost::detail::winapi::DWORD_ JOB_OBJECT_LIMIT_BREAKAWAY_OK_ = 0x00000800;
+
+}}}}}
+
+
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_ */
diff --git a/boost/process/detail/windows/locale.hpp b/boost/process/detail/windows/locale.hpp
new file mode 100644
index 0000000000..34da2a69d3
--- /dev/null
+++ b/boost/process/detail/windows/locale.hpp
@@ -0,0 +1,103 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+// Copyright (c) 2008 Beman Dawes
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_LOCALE_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_LOCALE_HPP_
+
+#include <locale>
+#include <boost/core/ignore_unused.hpp>
+#include <boost/detail/winapi/file_management.hpp>
+#include <boost/detail/winapi/character_code_conversion.hpp>
+
+namespace boost
+{
+namespace process
+{
+namespace detail
+{
+namespace windows
+{
+
+//copied from boost.filesystem
+class windows_file_codecvt
+ : public std::codecvt< wchar_t, char, std::mbstate_t >
+ {
+ public:
+ explicit windows_file_codecvt(std::size_t refs = 0)
+ : std::codecvt<wchar_t, char, std::mbstate_t>(refs) {}
+ protected:
+
+ bool do_always_noconv() const noexcept override { return false; }
+
+ // seems safest to assume variable number of characters since we don't
+ // actually know what codepage is active
+ int do_encoding() const noexcept override { return 0; }
+
+ std::codecvt_base::result do_in(std::mbstate_t& state,
+ const char* from, const char* from_end, const char*& from_next,
+ wchar_t* to, wchar_t* to_end, wchar_t*& to_next) const override
+ {
+ boost::ignore_unused(state);
+ ::boost::detail::winapi::UINT_ codepage = AreFileApisANSI() ?
+ ::boost::detail::winapi::CP_ACP_ :
+ ::boost::detail::winapi::CP_OEMCP_;
+
+ int count;
+ if ((count = ::boost::detail::winapi::MultiByteToWideChar(codepage,
+ ::boost::detail::winapi::MB_PRECOMPOSED_, from,
+ static_cast<int>(from_end - from), to, static_cast<int>(to_end - to))) == 0)
+ {
+ return error; // conversion failed
+ }
+
+ from_next = from_end;
+ to_next = to + count;
+ *to_next = L'\0';
+ return ok;
+ }
+
+ std::codecvt_base::result do_out(std::mbstate_t & state,
+ const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,
+ char* to, char* to_end, char*& to_next) const override
+ {
+ boost::ignore_unused(state);
+ auto codepage = ::boost::detail::winapi::AreFileApisANSI() ?
+ ::boost::detail::winapi::CP_ACP_ :
+ ::boost::detail::winapi::CP_OEMCP_;
+
+ int count;
+ if ((count = ::boost::detail::winapi::WideCharToMultiByte(codepage,
+ ::boost::detail::winapi::WC_NO_BEST_FIT_CHARS_, from,
+ static_cast<int>(from_end - from), to, static_cast<int>(to_end - to), 0, 0)) == 0)
+ {
+ return error; // conversion failed
+ }
+
+ from_next = from_end;
+ to_next = to + count;
+ *to_next = '\0';
+ return ok;
+ }
+
+ std::codecvt_base::result do_unshift(std::mbstate_t&,
+ char* /*from*/, char* /*to*/, char* & /*next*/) const override { return ok; }
+
+ int do_length(std::mbstate_t&,
+ const char* /*from*/, const char* /*from_end*/, std::size_t /*max*/) const override { return 0; }
+
+ int do_max_length() const noexcept override { return 0; }
+ };
+
+
+
+}
+}
+}
+}
+
+
+
+#endif /* BOOST_PROCESS_LOCALE_HPP_ */
diff --git a/boost/process/detail/windows/null_in.hpp b/boost/process/detail/windows/null_in.hpp
new file mode 100644
index 0000000000..f5c0ae6bf7
--- /dev/null
+++ b/boost/process/detail/windows/null_in.hpp
@@ -0,0 +1,41 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_IN_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_IN_HPP
+
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/detail/winapi/handle_info.hpp>
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/windows/file_descriptor.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+struct null_in : public ::boost::process::detail::handler_base
+{
+ file_descriptor source{"NUL", file_descriptor::read};
+
+public:
+ template <class WindowsExecutor>
+ void on_setup(WindowsExecutor &e) const
+ {
+ boost::detail::winapi::SetHandleInformation(source.handle(),
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ e.startup_info.hStdInput = source.handle();
+ e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+ }
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/null_out.hpp b/boost/process/detail/windows/null_out.hpp
new file mode 100644
index 0000000000..1bc19586c1
--- /dev/null
+++ b/boost/process/detail/windows/null_out.hpp
@@ -0,0 +1,75 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_OUT_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_OUT_HPP
+
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/detail/winapi/handle_info.hpp>
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/windows/file_descriptor.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+template<int p1, int p2>
+struct null_out : public ::boost::process::detail::handler_base
+{
+ file_descriptor sink {"NUL", file_descriptor::write}; //works because it gets destroyed AFTER launch.
+
+ template <typename WindowsExecutor>
+ void on_setup(WindowsExecutor &e) const;
+};
+
+template<>
+template<typename WindowsExecutor>
+void null_out<1,-1>::on_setup(WindowsExecutor &e) const
+{
+ boost::detail::winapi::SetHandleInformation(sink.handle(),
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ e.startup_info.hStdOutput = sink.handle();
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+
+}
+
+template<>
+template<typename WindowsExecutor>
+void null_out<2,-1>::on_setup(WindowsExecutor &e) const
+{
+ boost::detail::winapi::SetHandleInformation(sink.handle(),
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ e.startup_info.hStdError = sink.handle();
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+
+}
+
+template<>
+template<typename WindowsExecutor>
+void null_out<1,2>::on_setup(WindowsExecutor &e) const
+{
+ boost::detail::winapi::SetHandleInformation(sink.handle(),
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ e.startup_info.hStdOutput = sink.handle();
+ e.startup_info.hStdError = sink.handle();
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/on_exit.hpp b/boost/process/detail/windows/on_exit.hpp
new file mode 100644
index 0000000000..751f6a5f85
--- /dev/null
+++ b/boost/process/detail/windows/on_exit.hpp
@@ -0,0 +1,40 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_ON_EXIT_HPP_
+#define BOOST_PROCESS_WINDOWS_ON_EXIT_HPP_
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/windows/async_handler.hpp>
+#include <boost/detail/winapi/process.hpp>
+#include <system_error>
+#include <functional>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+struct on_exit_ : boost::process::detail::windows::async_handler
+{
+ std::function<void(int, const std::error_code&)> handler;
+ on_exit_(const std::function<void(int, const std::error_code&)> & handler) : handler(handler)
+ {
+
+ }
+
+ template<typename Executor>
+ std::function<void(int, const std::error_code&)> on_exit_handler(Executor&)
+ {
+ auto handler = this->handler;
+ return [handler](int exit_code, const std::error_code & ec)
+ {
+ handler(static_cast<int>(exit_code), ec);
+ };
+
+ }
+};
+
+
+}}}}
+#endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ON_EXIT_HPP_ */
diff --git a/boost/process/detail/windows/pipe_in.hpp b/boost/process/detail/windows/pipe_in.hpp
new file mode 100644
index 0000000000..cd8c186e15
--- /dev/null
+++ b/boost/process/detail/windows/pipe_in.hpp
@@ -0,0 +1,89 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_PIPE_IN_HPP
+#define BOOST_PROCESS_WINDOWS_INITIALIZERS_PIPE_IN_HPP
+
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/process/detail/handler_base.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+struct pipe_in : public ::boost::process::detail::handler_base
+{
+ ::boost::detail::winapi::HANDLE_ handle;
+
+ pipe_in(::boost::detail::winapi::HANDLE_ handle) : handle(handle) {}
+
+ template<typename T> //async_pipe
+ pipe_in(T & p) : handle(p.native_source())
+ {
+ p.assign_source(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
+ }
+
+ template <class WindowsExecutor>
+ void on_setup(WindowsExecutor &e) const
+ {
+ boost::detail::winapi::SetHandleInformation(handle,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ e.startup_info.hStdInput = handle;
+ e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+ }
+ template<typename WindowsExecutor>
+ void on_error(WindowsExecutor &, const std::error_code &) const
+ {
+ ::boost::detail::winapi::CloseHandle(handle);
+ }
+
+ template<typename WindowsExecutor>
+ void on_success(WindowsExecutor &) const
+ {
+ ::boost::detail::winapi::CloseHandle(handle);
+ }
+};
+
+class async_pipe;
+
+struct async_pipe_in : public pipe_in
+{
+ async_pipe &pipe;
+
+ template<typename AsyncPipe>
+ async_pipe_in(AsyncPipe & p) : pipe_in(p.native_source()), pipe(p)
+ {
+ }
+
+ template<typename Pipe, typename Executor>
+ static void close(Pipe & pipe, Executor &)
+ {
+ boost::system::error_code ec;
+ std::move(pipe).source().close(ec);
+ }
+
+ template<typename Executor>
+ void on_error(Executor & exec, const std::error_code &)
+ {
+ close(pipe, exec);
+ }
+
+ template<typename Executor>
+ void on_success(Executor &exec)
+ {
+ close(pipe, exec);
+ }
+};
+
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/pipe_out.hpp b/boost/process/detail/windows/pipe_out.hpp
new file mode 100644
index 0000000000..c32f0a604e
--- /dev/null
+++ b/boost/process/detail/windows/pipe_out.hpp
@@ -0,0 +1,122 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_PIPE_OUT_HPP
+#define BOOST_PROCESS_WINDOWS_PIPE_OUT_HPP
+
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/handles.hpp>
+#include <boost/process/detail/handler_base.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+
+
+template<int p1, int p2>
+struct pipe_out : public ::boost::process::detail::handler_base
+{
+ ::boost::detail::winapi::HANDLE_ handle;
+
+ pipe_out(::boost::detail::winapi::HANDLE_ handle) : handle(handle) {}
+ template<typename T>
+ pipe_out(T & p) : handle(p.native_sink())
+ {
+ p.assign_sink(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
+ }
+
+ template<typename WindowsExecutor>
+ void on_setup(WindowsExecutor &e) const;
+
+ template<typename WindowsExecutor>
+ void on_error(WindowsExecutor &, const std::error_code &) const
+ {
+ ::boost::detail::winapi::CloseHandle(handle);
+ }
+
+ template<typename WindowsExecutor>
+ void on_success(WindowsExecutor &) const
+ {
+ ::boost::detail::winapi::CloseHandle(handle);
+ }
+};
+
+template<>
+template<typename WindowsExecutor>
+void pipe_out<1,-1>::on_setup(WindowsExecutor &e) const
+{
+ boost::detail::winapi::SetHandleInformation(handle,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ e.startup_info.hStdOutput = handle;
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+}
+
+template<>
+template<typename WindowsExecutor>
+void pipe_out<2,-1>::on_setup(WindowsExecutor &e) const
+{
+ boost::detail::winapi::SetHandleInformation(handle,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+
+ e.startup_info.hStdError = handle;
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+}
+
+template<>
+template<typename WindowsExecutor>
+void pipe_out<1,2>::on_setup(WindowsExecutor &e) const
+{
+ boost::detail::winapi::SetHandleInformation(handle,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_,
+ boost::detail::winapi::HANDLE_FLAG_INHERIT_);
+
+ e.startup_info.hStdOutput = handle;
+ e.startup_info.hStdError = handle;
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
+ e.inherit_handles = true;
+}
+
+template<int p1, int p2>
+struct async_pipe_out : public pipe_out<p1, p2>
+{
+ async_pipe &pipe;
+ template<typename AsyncPipe>
+ async_pipe_out(AsyncPipe & p) : pipe_out<p1, p2>(p.native_sink()), pipe(p)
+ {
+ }
+
+ template<typename Pipe, typename Executor>
+ static void close(Pipe & pipe, Executor &)
+ {
+ boost::system::error_code ec;
+ std::move(pipe).sink().close(ec);
+ }
+
+ template<typename Executor>
+ void on_error(Executor & exec, const std::error_code &)
+ {
+ close(pipe, exec);
+ }
+
+ template<typename Executor>
+ void on_success(Executor &exec)
+ {
+ close(pipe, exec);
+ }
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/search_path.hpp b/boost/process/detail/windows/search_path.hpp
new file mode 100644
index 0000000000..53fb966784
--- /dev/null
+++ b/boost/process/detail/windows/search_path.hpp
@@ -0,0 +1,54 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_SEARCH_PATH_HPP
+#define BOOST_PROCESS_WINDOWS_SEARCH_PATH_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/system/error_code.hpp>
+#include <string>
+#include <stdexcept>
+#include <array>
+#include <atomic>
+#include <cstdlib>
+#include <boost/detail/winapi/shell.hpp>
+
+
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+inline boost::filesystem::path search_path(
+ const boost::filesystem::path &filename,
+ const std::vector<boost::filesystem::path> &path)
+{
+ for (const boost::filesystem::path & pp : path)
+ {
+ auto full = pp / filename;
+ std::array<std::string, 4> extensions {{ "", ".exe", ".com", ".bat" }};
+ for (boost::filesystem::path ext : extensions)
+ {
+ auto p = full;
+ p += ext;
+ boost::system::error_code ec;
+ bool file = boost::filesystem::is_regular_file(p, ec);
+ if (!ec && file &&
+ ::boost::detail::winapi::sh_get_file_info(p.string().c_str(), 0, 0, 0, ::boost::detail::winapi::SHGFI_EXETYPE_))
+ {
+ return p;
+ }
+ }
+ }
+ return "";
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/shell_path.hpp b/boost/process/detail/windows/shell_path.hpp
new file mode 100644
index 0000000000..7cce445292
--- /dev/null
+++ b/boost/process/detail/windows/shell_path.hpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_SHELL_PATH_HPP
+#define BOOST_PROCESS_WINDOWS_SHELL_PATH_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <system_error>
+#include <boost/filesystem/path.hpp>
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/get_system_directory.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+inline boost::filesystem::path shell_path()
+{
+ ::boost::detail::winapi::WCHAR_ sysdir[260];
+ unsigned int size = ::boost::detail::winapi::get_system_directory(sysdir, sizeof(sysdir));
+ if (!size)
+ throw_last_error("GetSystemDirectory() failed");
+
+ boost::filesystem::path p = sysdir;
+ return p / "cmd.exe";
+}
+
+inline boost::filesystem::path shell_path(std::error_code &ec) noexcept
+{
+
+ ::boost::detail::winapi::WCHAR_ sysdir[260];
+ unsigned int size = ::boost::detail::winapi::get_system_directory(sysdir, sizeof(sysdir));
+ boost::filesystem::path p;
+ if (!size)
+ ec = std::error_code(
+ ::boost::detail::winapi::GetLastError(),
+ std::system_category());
+ else
+ {
+ ec.clear();
+ p = sysdir;
+ p /= "cmd.exe";
+ }
+ return p;
+}
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/show_window.hpp b/boost/process/detail/windows/show_window.hpp
new file mode 100644
index 0000000000..ed42ebc56e
--- /dev/null
+++ b/boost/process/detail/windows/show_window.hpp
@@ -0,0 +1,39 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_SHOW_WINDOW_HPP
+#define BOOST_PROCESS_WINDOWS_SHOW_WINDOW_HPP
+
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/show_window.hpp>
+#include <boost/process/detail/handler_base.hpp>
+
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+template<::boost::detail::winapi::WORD_ Flags>
+struct show_window : ::boost::process::detail::handler_base
+{
+ template <class WindowsExecutor>
+ void on_setup(WindowsExecutor &e) const
+ {
+ e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESHOWWINDOW_;
+ e.startup_info.wShowWindow |= Flags;
+ }
+};
+
+
+
+
+
+}}}}
+
+#endif
+
diff --git a/boost/process/detail/windows/start_dir.hpp b/boost/process/detail/windows/start_dir.hpp
new file mode 100644
index 0000000000..06629ed1f8
--- /dev/null
+++ b/boost/process/detail/windows/start_dir.hpp
@@ -0,0 +1,36 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_START_DIR_HPP
+#define BOOST_PROCESS_DETAIL_WINDOWS_START_DIR_HPP
+
+#include <string>
+#include <boost/process/detail/windows/handler.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+template<typename Char>
+struct start_dir_init : handler_base_ext
+{
+ start_dir_init(const std::basic_string<Char> &s) : s_(s) {}
+
+ template <class Executor>
+ void on_setup(Executor& exec) const
+ {
+ exec.work_dir = s_.c_str();
+ }
+
+ const std::basic_string<Char> &str() const {return s_;}
+private:
+ std::basic_string<Char> s_;
+};
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/terminate.hpp b/boost/process/detail/windows/terminate.hpp
new file mode 100644
index 0000000000..a10b074078
--- /dev/null
+++ b/boost/process/detail/windows/terminate.hpp
@@ -0,0 +1,49 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_TERMINATE_HPP
+#define BOOST_PROCESS_WINDOWS_TERMINATE_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <system_error>
+#include <cstdlib>
+#include <boost/detail/winapi/process.hpp>
+#include <boost/detail/winapi/get_last_error.hpp>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+struct child_handle;
+
+inline void terminate(child_handle &p)
+{
+ if (!::boost::detail::winapi::TerminateProcess(p.process_handle(), EXIT_FAILURE))
+ boost::process::detail::throw_last_error("TerminateProcess() failed");
+
+ ::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
+ p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+}
+
+inline void terminate(child_handle &p, std::error_code &ec) noexcept
+{
+ if (!::boost::detail::winapi::TerminateProcess(p.process_handle(), EXIT_FAILURE))
+ ec = boost::process::detail::get_last_error();
+ else
+ {
+ ec.clear();
+ ::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
+ p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ }
+}
+
+
+
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/wait_for_exit.hpp b/boost/process/detail/windows/wait_for_exit.hpp
new file mode 100644
index 0000000000..decdb51172
--- /dev/null
+++ b/boost/process/detail/windows/wait_for_exit.hpp
@@ -0,0 +1,193 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_WINDOWS_WAIT_FOR_EXIT_HPP
+#define BOOST_PROCESS_WINDOWS_WAIT_FOR_EXIT_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <system_error>
+#include <boost/detail/winapi/synchronization.hpp>
+#include <boost/detail/winapi/process.hpp>
+#include <boost/process/detail/windows/child_handle.hpp>
+#include <chrono>
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+inline void wait(child_handle &p, int & exit_code)
+{
+ if (::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
+ ::boost::detail::winapi::infinite) == ::boost::detail::winapi::wait_failed)
+ throw_last_error("WaitForSingleObject() failed");
+
+ ::boost::detail::winapi::DWORD_ _exit_code;
+ if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
+ throw_last_error("GetExitCodeProcess() failed");
+
+ ::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
+ p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ exit_code = static_cast<int>(_exit_code);
+}
+
+inline void wait(child_handle &p, int & exit_code, std::error_code &ec) noexcept
+{
+ ::boost::detail::winapi::DWORD_ _exit_code = 1;
+
+ if (::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
+ ::boost::detail::winapi::infinite) == ::boost::detail::winapi::wait_failed)
+ ec = std::error_code(
+ ::boost::detail::winapi::GetLastError(),
+ std::system_category());
+ else if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
+ ec = std::error_code(
+ ::boost::detail::winapi::GetLastError(),
+ std::system_category());
+ else
+ ec.clear();
+
+ ::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
+ p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ exit_code = static_cast<int>(_exit_code);
+}
+
+
+template< class Rep, class Period >
+inline bool wait_for(
+ child_handle &p,
+ int & exit_code,
+ const std::chrono::duration<Rep, Period>& rel_time)
+{
+
+ std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
+
+ ::boost::detail::winapi::DWORD_ wait_code;
+ wait_code = ::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
+ static_cast<::boost::detail::winapi::DWORD_>(ms.count()));
+ if (wait_code == ::boost::detail::winapi::wait_failed)
+ throw_last_error("WaitForSingleObject() failed");
+ else if (wait_code == ::boost::detail::winapi::wait_timeout)
+ return false; //
+
+ ::boost::detail::winapi::DWORD_ _exit_code;
+ if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
+ throw_last_error("GetExitCodeProcess() failed");
+
+ exit_code = static_cast<int>(_exit_code);
+ ::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
+ p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ return true;
+}
+
+
+template< class Rep, class Period >
+inline bool wait_for(
+ child_handle &p,
+ int & exit_code,
+ const std::chrono::duration<Rep, Period>& rel_time,
+ std::error_code &ec) noexcept
+{
+
+ std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
+
+
+ ::boost::detail::winapi::DWORD_ wait_code;
+ wait_code = ::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
+ static_cast<::boost::detail::winapi::DWORD_>(ms.count()));
+ if (wait_code == ::boost::detail::winapi::wait_failed)
+ ec = std::error_code(
+ ::boost::detail::winapi::GetLastError(),
+ std::system_category());
+ else if (wait_code == ::boost::detail::winapi::wait_timeout)
+ return false; //
+
+ ::boost::detail::winapi::DWORD_ _exit_code = 1;
+ if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
+ {
+ ec = std::error_code(
+ ::boost::detail::winapi::GetLastError(),
+ std::system_category());
+ return false;
+ }
+ else
+ ec.clear();
+
+ exit_code = static_cast<int>(_exit_code);
+ ::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
+ p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ return true;
+;
+}
+
+template< class Clock, class Duration >
+inline bool wait_until(
+ child_handle &p,
+ int & exit_code,
+ const std::chrono::time_point<Clock, Duration>& timeout_time)
+{
+ std::chrono::milliseconds ms =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ timeout_time - std::chrono::system_clock::now());
+
+ ::boost::detail::winapi::DWORD_ wait_code;
+ wait_code = ::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
+ static_cast<::boost::detail::winapi::DWORD_>(ms.count()));
+
+ if (wait_code == ::boost::detail::winapi::wait_failed)
+ throw_last_error("WaitForSingleObject() failed");
+ else if (wait_code == ::boost::detail::winapi::wait_timeout)
+ return false;
+
+ ::boost::detail::winapi::DWORD_ _exit_code;
+ if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
+ throw_last_error("GetExitCodeProcess() failed");
+
+ exit_code = static_cast<int>(_exit_code);
+ ::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
+ p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ return true;
+}
+
+
+template< class Clock, class Duration >
+inline bool wait_until(
+ child_handle &p,
+ int & exit_code,
+ const std::chrono::time_point<Clock, Duration>& timeout_time,
+ std::error_code &ec) noexcept
+{
+ std::chrono::milliseconds ms =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ timeout_time - std::chrono::system_clock::now());
+
+ ::boost::detail::winapi::DWORD_ _exit_code = 1;
+
+ if (::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
+ static_cast<::boost::detail::winapi::DWORD_>(ms.count()))
+ == ::boost::detail::winapi::wait_failed)
+ ec = std::error_code(
+ ::boost::detail::winapi::GetLastError(),
+ std::system_category());
+ else if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
+ ec = std::error_code(
+ ::boost::detail::winapi::GetLastError(),
+ std::system_category());
+ else
+ ec.clear();
+
+ exit_code = static_cast<int>(exit_code);
+ ::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
+ p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
+ return true;
+;
+}
+
+
+}}}}
+
+#endif
diff --git a/boost/process/detail/windows/wait_group.hpp b/boost/process/detail/windows/wait_group.hpp
new file mode 100644
index 0000000000..449985f2fc
--- /dev/null
+++ b/boost/process/detail/windows/wait_group.hpp
@@ -0,0 +1,121 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_WINDOWS_WAIT_GROUP_HPP_
+#define BOOST_PROCESS_DETAIL_WINDOWS_WAIT_GROUP_HPP_
+
+#include <boost/process/detail/config.hpp>
+#include <boost/detail/winapi/jobs.hpp>
+#include <boost/detail/winapi/wait.hpp>
+
+
+namespace boost { namespace process { namespace detail { namespace windows {
+
+struct group_handle;
+
+inline void wait(const group_handle &p)
+{
+ if (::boost::detail::winapi::WaitForSingleObject(p.handle(),
+ ::boost::detail::winapi::infinite) == ::boost::detail::winapi::wait_failed)
+ throw_last_error("WaitForSingleObject() failed");
+
+}
+
+inline void wait(const group_handle &p, std::error_code &ec)
+{
+ if (::boost::detail::winapi::WaitForSingleObject(p.handle(),
+ ::boost::detail::winapi::infinite) == ::boost::detail::winapi::wait_failed)
+ ec = get_last_error();
+}
+
+
+template< class Rep, class Period >
+inline bool wait_for(
+ const group_handle &p,
+ const std::chrono::duration<Rep, Period>& rel_time)
+{
+
+ std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
+
+ ::boost::detail::winapi::DWORD_ wait_code;
+ wait_code = ::boost::detail::winapi::WaitForSingleObject(p.handle(), ms.count());
+ if (wait_code == ::boost::detail::winapi::wait_failed)
+ throw_last_error("WaitForSingleObject() failed");
+ else if (wait_code == ::boost::detail::winapi::wait_timeout)
+ return false; //
+
+ return true;
+}
+
+
+template< class Rep, class Period >
+inline bool wait_for(
+ const group_handle &p,
+ const std::chrono::duration<Rep, Period>& rel_time,
+ std::error_code &ec)
+{
+
+ std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
+
+
+ ::boost::detail::winapi::DWORD_ wait_code;
+ wait_code = ::boost::detail::winapi::WaitForSingleObject(p.handle(), ms.count());
+ if (wait_code == ::boost::detail::winapi::wait_failed)
+ ec = get_last_error();
+
+ else if (wait_code == ::boost::detail::winapi::wait_timeout)
+ return false; //
+
+ return true;
+}
+
+template< class Clock, class Duration >
+inline bool wait_until(
+ const group_handle &p,
+ const std::chrono::time_point<Clock, Duration>& timeout_time)
+{
+ std::chrono::milliseconds ms =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ timeout_time - std::chrono::system_clock::now());
+
+ ::boost::detail::winapi::DWORD_ wait_code;
+ wait_code = ::boost::detail::winapi::WaitForSingleObject(p.handle(), ms.count());
+
+ if (wait_code == ::boost::detail::winapi::wait_failed)
+ throw_last_error("WaitForSingleObject() failed");
+
+ else if (wait_code == ::boost::detail::winapi::wait_timeout)
+ return false; //
+
+ return true;
+}
+
+
+template< class Clock, class Duration >
+inline bool wait_until(
+ const group_handle &p,
+ const std::chrono::time_point<Clock, Duration>& timeout_time,
+ std::error_code &ec)
+{
+ std::chrono::milliseconds ms =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ timeout_time - std::chrono::system_clock::now());
+
+ ::boost::detail::winapi::DWORD_ wait_code;
+ wait_code = ::boost::detail::winapi::WaitForSingleObject(p.handle(), ms.count());
+
+ if (wait_code == ::boost::detail::winapi::wait_failed)
+ ec = get_last_error();
+
+ else if (wait_code == ::boost::detail::winapi::wait_timeout)
+ return false; //
+
+ return true;
+;
+}
+
+}}}}
+
+#endif /* BOOST_PROCESS_DETAIL_WINDOWS_WAIT_GROUP_HPP_ */
diff --git a/boost/process/env.hpp b/boost/process/env.hpp
new file mode 100644
index 0000000000..4362b0fe86
--- /dev/null
+++ b/boost/process/env.hpp
@@ -0,0 +1,502 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_ENV_HPP_
+#define BOOST_PROCESS_DETAIL_ENV_HPP_
+
+#include <boost/process/environment.hpp>
+#include <boost/none.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/env_init.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/env_init.hpp>
+#endif
+
+/** \file boost/process/env.hpp
+ *
+ * This header which provides the `env` property. It allows the modification of the
+ * environment the child process will run in, in a functional style.
+ *
+ * \xmlonly
+<programlisting>
+namespace boost {
+ namespace process {
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::env">env</globalname>;
+ }
+}
+</programlisting>
+ * \endxmlonly
+ *
+ * For additional information see the platform documentations:
+ *
+ * - [windows](https://msdn.microsoft.com/en-US/library/windows/desktop/ms682653.aspx)
+ * - [posix](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html)
+ *
+ */
+
+
+namespace boost {
+
+namespace process { namespace detail {
+
+
+template<typename Char>
+std::size_t make_env_string_size(const std::basic_string<Char> & ch)
+{
+ return ch.size() + 1;
+}
+
+template<typename Char>
+std::size_t make_env_string_size(const Char * ch)
+{
+ std::size_t sz = 0;
+ while (ch[sz] != null_char<Char>())
+ sz++;
+
+ sz++;
+ return sz;
+}
+
+template<typename Char, typename Container>
+inline std::basic_string<Char> make_env_string(const Container & value)
+{
+ std::size_t sz = 0;
+ for (auto & v : value)
+ sz += make_env_string_size(v);
+
+ std::basic_string<Char> s;
+ s.reserve(sz); //+1 for ;, end doesn't have one.
+
+ for (auto & val : value)
+ (s += val) += api::env_seperator<Char>();
+
+ s.resize(s.size() -1); //remove last ';'
+ return s;
+}
+
+
+template<typename Char>
+struct env_set
+{
+ using string_type = std::basic_string<Char>;
+ string_type key;
+ string_type value;
+};
+
+template<typename Char>
+struct env_append
+{
+ using string_type = std::basic_string<Char>;
+ string_type key;
+ string_type value;
+};
+
+
+
+template<typename Char>
+struct env_reset
+{
+ using string_type = std::basic_string<Char>;
+ string_type key;
+};
+
+
+template<> struct is_wchar_t<env_set<wchar_t>> : std::true_type {};
+template<> struct is_wchar_t<env_append<wchar_t>> : std::true_type {};
+template<> struct is_wchar_t<env_reset<wchar_t>> : std::true_type {};
+template<> struct is_wchar_t<basic_environment<wchar_t>> : std::true_type {};
+
+
+template<>
+struct char_converter<char, env_set<wchar_t>>
+{
+ static env_set<char> conv(const env_set<wchar_t> & in)
+ {
+ return {::boost::process::detail::convert(in.key),
+ ::boost::process::detail::convert(in.value)};
+ }
+};
+
+template<>
+struct char_converter<wchar_t, env_set<char>>
+{
+ static env_set<wchar_t> conv(const env_set<char> & in)
+ {
+ return {::boost::process::detail::convert(in.key),
+ ::boost::process::detail::convert(in.value)};
+ }
+};
+
+template<>
+struct char_converter<char, env_append<wchar_t>>
+{
+ static env_append<char> conv(const env_append<wchar_t> & in)
+ {
+ return {::boost::process::detail::convert(in.key),
+ ::boost::process::detail::convert(in.value)};
+ }
+};
+
+template<>
+struct char_converter<wchar_t, env_append<char>>
+{
+ static env_append<wchar_t> conv(const env_append<char> & in)
+ {
+ return {::boost::process::detail::convert(in.key),
+ ::boost::process::detail::convert(in.value)};
+ }
+};
+
+template<>
+struct char_converter<char, env_reset<wchar_t>>
+{
+ static env_reset<char> conv(const env_reset<wchar_t> & in)
+ {
+ return {::boost::process::detail::convert(in.key)};
+ }
+};
+
+template<>
+struct char_converter<wchar_t, env_reset<char>>
+{
+ static env_reset<wchar_t> conv(const env_reset<char> & in)
+ {
+ return {::boost::process::detail::convert(in.key)};
+ }
+};
+
+
+template<typename Char>
+struct env_init
+{
+ basic_environment<Char> env;
+};
+
+template<>
+struct char_converter<char, env_init<wchar_t>>
+{
+ static env_init<char> conv(const env_init<wchar_t> & in)
+ {
+ return {basic_environment<char>(in.env)};
+ }
+};
+
+template<>
+struct char_converter<wchar_t, env_init<char>>
+{
+ static env_init<wchar_t> conv(const env_init<char> & in)
+ {
+ return {basic_environment<wchar_t>(in.env)};
+ }
+};
+
+template<>
+struct char_converter<char, basic_environment<wchar_t>>
+{
+ static basic_environment<char> conv(const basic_environment<wchar_t> & in)
+ {
+ return { basic_environment<char>(in) };
+ }
+};
+
+template<>
+struct char_converter<wchar_t, basic_environment<char>>
+{
+ static basic_environment<wchar_t> conv(const basic_environment<char> & in)
+ {
+ return { basic_environment<wchar_t>(in) };
+ }
+};
+
+template<typename Char>
+struct env_proxy
+{
+ using string_type = std::basic_string<Char>;
+ string_type key;
+
+
+ env_set<Char> operator=(const string_type & value)
+ {
+ return {std::move(key), value};
+ }
+ env_set<Char> operator=(const std::vector<string_type> & value)
+ {
+ return {std::move(key), make_env_string<Char>(value)};
+ }
+ env_set<Char> operator=(const std::initializer_list<const Char*> & value)
+ {
+ return {std::move(key), make_env_string<Char>(value)};
+ }
+
+ env_append<Char> operator+=(const string_type & value)
+ {
+ return {std::move(key), value};
+ }
+ env_append<Char> operator+=(const std::vector<string_type> & value)
+ {
+ return {std::move(key), make_env_string<Char>(value)};
+ }
+ env_append<Char> operator+=(const std::initializer_list<const Char*> & value)
+ {
+ return {std::move(key), make_env_string<Char>(value)};
+ }
+ env_reset<Char> operator=(boost::none_t)
+ {
+ return {std::move(key)};
+ }
+};
+
+struct env_
+{
+ constexpr env_() {};
+
+ template<typename Char>
+ env_set<Char> operator()(const std::basic_string<Char> & key,
+ const std::basic_string<Char> & value) const
+ {
+ return {key, value};
+ }
+ template<typename Char>
+ env_set<Char> operator()(const std::basic_string<Char> & key,
+ const std::vector<std::basic_string<Char>> & value) const
+ {
+ return {key, make_env_string<Char>(value)};
+ }
+ template<typename Char>
+ env_set<Char> operator()(const std::basic_string<Char> & key,
+ const std::initializer_list<Char*> & value) const
+ {
+ return {key, make_env_string<Char>(value)};
+ }
+ template<typename Char>
+ env_reset<Char> operator()(const std::basic_string<Char> & key, boost::none_t)
+ {
+ return {key};
+ }
+ template<typename Char>
+ env_proxy<Char> operator[](const std::basic_string<Char> & key) const
+ {
+ return {key};
+ }
+ template<typename Char>
+ env_proxy<Char> operator[](const Char* key) const
+ {
+ return {key};
+ }
+ template<typename Char>
+ env_init<Char> operator()(const basic_environment<Char> & env) const
+ {
+ return {env};
+ }
+ template<typename Char>
+ env_init<Char> operator= (const basic_environment<Char> & env) const
+ {
+ return {env};
+ }
+};
+
+template<typename Char>
+struct env_builder
+{
+ basic_environment<Char> env;
+ env_builder() : env{basic_native_environment<Char>()} {}
+
+ void operator()(const basic_environment<Char> & e)
+ {
+ env = e;
+ }
+
+ void operator()(env_init<Char> & ei)
+ {
+ env = std::move(ei.env);
+ }
+ void operator()(env_set<Char> & es)
+ {
+ env[es.key] = es.value;
+ }
+ void operator()(env_reset<Char> & es)
+ {
+ env.erase(es.key);
+ }
+ template<typename T>
+ void operator()(env_append<T> & es)
+ {
+ env[es.key] += es.value;
+ }
+
+ typedef api::env_init<Char> result_type;
+ api::env_init<Char> get_initializer()
+ {
+ return api::env_init<Char>(std::move(env));
+ }
+};
+
+template<>
+struct initializer_builder<env_tag<char>>
+{
+ typedef env_builder<char> type;
+};
+
+template<>
+struct initializer_builder<env_tag<wchar_t>>
+{
+ typedef env_builder<wchar_t> type;
+};
+
+}
+
+/**
+
+The `env` property provides a functional way to modify the environment used by
+the child process. If none is passed the environment is inherited from the father
+process. Appending means that the environment will be interpreted as a ';' or ':'
+seperated list as used in `PATH`.
+
+On both `posix` and `windows` the environment variables can be lists of strings,
+seperated by ';'. This is typically used for the `PATH` variable.
+
+By default the environment will be inherited from the launching process,
+which is also true if environment are modified with this initializer.
+
+\section env_details Details
+
+\subsection env_operations Operations
+
+\subsubsection env_set_var Setting variables
+
+To set a variable `id` the value `value` the following syntax can be used.
+
+\code{.cpp}
+env[id] = value;
+env(id, value);
+\endcode
+
+`std::initializer_list` is among the allowed types, so the following syntax is also possible.
+
+\code{.cpp}
+env[id] = {value1, value2};
+env(id, {value1, value2});
+\endcode
+
+\note Creates the variable if it does not exist.
+
+The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`
+for both `id` and `value`.
+
+\paragraph id id
+
+ - `std::basic_string<char_type>`
+ - `const char_type *`
+
+\paragraph env_set_var_value value
+
+ - `std::basic_string<char_type>`
+ - `const char_type * `
+ - `std::initializer_list<const char_type *>`
+ - `std::vector<std::basic_string<char_type>>`
+
+
+\note Using `std::vector` or `std::initializer_list`
+
+\subsubsection env_append_var Append variables
+
+Appending means, that a variable will be interpreted as a
+To append a variable `id` the value `value` the following syntax can be used:
+
+\code{.cpp}
+env[id] += value;
+\endcode
+
+`std::initializer_list` is among the allowed types, so the following syntax is also possible.
+
+\code{.cpp}
+env[id] += {value1, value2};
+\endcode
+
+\note Creates the variable if it does not exist.
+
+The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`
+for both `id` and `value`.
+
+\paragraph env_append_var_id id
+
+ - `std::basic_string<char_type>`
+ - `const char_type *`
+
+\paragraph env_append_var_value value
+
+ - `std::basic_string<char_type>`
+ - `const char_type *`
+ - `std::initializer_list<const char_type *>`
+ - `std::vector<std::basic_string<char_type>>`
+
+
+\subsubsection env_reset Reset variables
+
+Reseting signle variables can be done in the following way:
+
+\code{.cpp}
+env[id] = boost::none;
+env(id, boost::none);
+\endcode
+
+\note This does not set the value empty, but removes it from the list.
+
+The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`:
+
+\paragraph env_reset_var_id id
+
+ - `std::basic_string<char_type>`
+ - `const char_type *`
+
+\subsubsection env_init Initialize the environment
+
+The whole environment can be initialized from an object of type
+\xmlonly <classname>boost::process::environment</classname> \endxmlonly
+
+\code{.cpp}
+env=env;
+env(env);
+\endcode
+
+\note The passed `environment` can also be default-constructed to get an empty environment.
+
+\paragraph env_init_var_id id
+
+ - `std::basic_string<char_type>`
+ - `const char_type *`
+
+\paragraph env_init_var_value value
+
+ - `boost::process::basic_environment<char_type>`
+
+\subsection env_example Example
+
+\code{.cpp}
+spawn("b2", env["PATH"]+="F:/boost", env["SOME_VAR"]=boost::none, env["NEW_VAR"]="VALUE");
+\endcode
+
+If the overload style should be done by passing an instance of
+\xmlonly <classname>boost::process::environment</classname> \endxmlonly
+the above example would look like this.
+
+\code{.cpp}
+environment e = this_process::environment();
+e["PATH"] += "F:/boost";
+e.erase("SOME_VAR");
+e["NEW_VAR"] = "VALUE";
+spawn("b2", e);
+\endcode
+
+\warning Passing an empty environment will cause undefined behaviour.
+
+ */
+constexpr boost::process::detail::env_ env{};
+
+
+}}
+
+#endif /* INCLUDE_BOOST_PROCESS_DETAIL_ENV_HPP_ */
diff --git a/boost/process/environment.hpp b/boost/process/environment.hpp
new file mode 100644
index 0000000000..1684798b87
--- /dev/null
+++ b/boost/process/environment.hpp
@@ -0,0 +1,698 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_ENVIRONMENT_HPP_
+#define BOOST_PROCESS_ENVIRONMENT_HPP_
+
+#include <boost/process/detail/config.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/case_conv.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/filesystem/path.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/environment.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/environment.hpp>
+#endif
+
+namespace boost { namespace process {
+
+namespace detail {
+
+template<typename Char, typename Environment>
+struct const_entry
+{
+ using value_type = Char ;
+ using pointer = const value_type * ;
+ using string_type = std::basic_string<value_type> ;
+ using range = boost::iterator_range<pointer> ;
+ using environment_t = Environment ;
+
+ std::vector<string_type> to_vector() const
+ {
+ if (_data == nullptr)
+ return std::vector<string_type>();
+ std::vector<string_type> data;
+ auto str = string_type(_data);
+ struct splitter
+ {
+ bool operator()(wchar_t w) const {return w == api::env_seperator<wchar_t>();}
+ bool operator()(char c) const {return c == api::env_seperator<char> ();}
+ } s;
+ boost::split(data, _data, s);
+ return std::move(data);
+ }
+ string_type to_string() const
+ {
+ if (_data != nullptr)
+ return string_type(_data);
+ else
+ return string_type();
+ }
+ string_type get_name() const {return string_type(_name.begin(), _name.end());}
+ explicit const_entry(string_type&& name, pointer data, environment_t & env_) :
+ _name(std::move(name)), _data(data), _env(&env_) {}
+
+ explicit const_entry(string_type &&name, environment_t & env) :
+ _name(std::move(name)), _data(nullptr), _env(&env) {}
+ const_entry(const const_entry&) = default;
+ const_entry& operator=(const const_entry&) = default;
+
+ void reload()
+ {
+ auto p = _env->find(_name);
+ if (p == _env->end())
+ _data = nullptr;
+ else
+ _data = p->_data;
+ this->_env->reload();
+
+ }
+ bool empty() const
+ {
+ return _data == nullptr;
+ }
+protected:
+ string_type _name;
+ pointer _data;
+ environment_t * _env;
+};
+
+template<typename Char, typename Environment>
+struct entry : const_entry<Char, Environment>
+{
+ using father = const_entry<Char, Environment>;
+ using value_type = typename father::value_type;
+ using string_type = typename father::string_type;
+ using pointer = typename father::pointer;
+ using environment_t = typename father::environment_t;
+
+ explicit entry(string_type&& name, pointer data, environment_t & env) :
+ father(std::move(name), data, env) {}
+
+ explicit entry(string_type &&name, environment_t & env) :
+ father(std::move(name), env) {}
+
+ entry(const entry&) = default;
+ entry& operator=(const entry&) = default;
+
+ void assign(const string_type &value)
+ {
+ this->_env->set(this->_name, value);
+ this->reload();
+ }
+ void assign(const std::vector<string_type> &value)
+ {
+ string_type data;
+ for (auto &v : value)
+ {
+ if (&v != &value.front())
+ data += api::env_seperator<value_type>();
+ data += v;
+ }
+ this->_env->set(this->_name, data);
+ this->reload();
+
+ }
+ void assign(const std::initializer_list<string_type> &value)
+ {
+ string_type data;
+ for (auto &v : value)
+ {
+ if (&v != &*value.begin())
+ data += api::env_seperator<value_type>();
+ data += v;
+ }
+ this->_env->set(this->_name, data);
+ this->reload();
+
+ }
+ void append(const string_type &value)
+ {
+ if (this->_data == nullptr)
+ this->_env->set(this->_name, value);
+ else
+ {
+ string_type st = this->_data;
+ this->_env->set(this->_name, st + api::env_seperator<value_type>() + value);
+ }
+
+
+ this->reload();
+
+ }
+ void clear()
+ {
+ this->_env->reset(this->_name);
+ this->_env->reload();
+ this->_data = nullptr;
+ }
+ entry &operator=(const string_type & value)
+ {
+ assign(value);
+ return *this;
+ }
+ entry &operator=(const std::vector<string_type> & value)
+ {
+ assign(value);
+ return *this;
+ }
+ entry &operator=(const std::initializer_list<string_type> & value)
+ {
+ assign(value);
+ return *this;
+ }
+ entry &operator+=(const string_type & value)
+ {
+ append(value);
+ return *this;
+ }
+
+};
+
+
+
+template<typename Char, typename Environment>
+struct make_entry
+{
+
+ make_entry(const make_entry&) = default;
+ make_entry& operator=(const make_entry&) = default;
+
+ Environment *env;
+ make_entry(Environment & env) : env(&env) {};
+ entry<Char, Environment> operator()(const Char* data) const
+ {
+ auto p = data;
+ while ((*p != equal_sign<Char>()) && (*p != null_char<Char>()))
+ p++;
+ auto name = std::basic_string<Char>(data, p);
+ p++; //go behind equal sign
+
+ return entry<Char, Environment>(std::move(name), p, *env);
+ }
+};
+
+template<typename Char, typename Environment>
+struct make_const_entry
+{
+
+ make_const_entry(const make_const_entry&) = default;
+ make_const_entry& operator=(const make_const_entry&) = default;
+
+ Environment *env;
+ make_const_entry(Environment & env) : env(&env) {};
+ const_entry<Char, Environment> operator()(const Char* data) const
+ {
+ auto p = data;
+ while ((*p != equal_sign<Char>()) && (*p != null_char<Char>()))
+ p++;
+ auto name = std::basic_string<Char>(data, p);
+ p++; //go behind equal sign
+
+ return const_entry<Char, Environment>(std::move(name), p, *env);
+ }
+};
+
+}
+
+#if !defined (BOOST_PROCESS_DOXYGEN)
+
+template<typename Char, template <class> class Implementation = detail::api::basic_environment_impl>
+class basic_environment_impl : public Implementation<Char>
+{
+ Char** _get_end() const
+ {
+ auto p = this->_env_impl;
+ while (*p != nullptr)
+ p++;
+
+ return p;
+ }
+public:
+ using string_type = std::basic_string<Char>;
+ using implementation_type = Implementation<Char>;
+ using base_type = basic_environment_impl<Char, Implementation>;
+ using entry_maker = detail::make_entry<Char, base_type>;
+ using entry_type = detail::entry <Char, base_type>;
+ using const_entry_type = detail::const_entry <Char, const base_type>;
+ using const_entry_maker = detail::make_const_entry<Char, const base_type>;
+
+ friend entry_type;
+ friend const_entry_type;
+
+ using iterator = boost::transform_iterator< entry_maker, Char**, entry_type, entry_type>;
+ using const_iterator = boost::transform_iterator<const_entry_maker, Char**, const_entry_type, const_entry_type>;
+ using size_type = std::size_t;
+
+ iterator begin() {return iterator(this->_env_impl, entry_maker(*this));}
+ const_iterator begin() const {return const_iterator(this->_env_impl, const_entry_maker(*this));}
+ const_iterator cbegin() const {return const_iterator(this->_env_impl, const_entry_maker(*this));}
+
+ iterator end() {return iterator(_get_end(), entry_maker(*this));}
+ const_iterator end() const {return const_iterator(_get_end(), const_entry_maker(*this));}
+ const_iterator cend() const {return const_iterator(_get_end(), const_entry_maker(*this));}
+
+ iterator find( const string_type& key )
+ {
+ auto p = this->_env_impl;
+ auto st1 = key + ::boost::process::detail::equal_sign<Char>();
+ while (*p != nullptr)
+ {
+ if (std::equal(st1.begin(), st1.end(), *p))
+ break;
+ p++;
+ }
+ return iterator(p, entry_maker(*this));
+ }
+ const_iterator find( const string_type& key ) const
+ {
+ auto p = this->_env_impl;
+ auto st1 = key + ::boost::process::detail::equal_sign<Char>();
+ while (*p != nullptr)
+ {
+ if (std::equal(st1.begin(), st1.end(), *p))
+ break;
+ p++;
+ }
+ return const_iterator(p, const_entry_maker(*this));
+ }
+
+ std::size_t count(const string_type & st) const
+ {
+ auto p = this->_env_impl;
+ auto st1 = st + ::boost::process::detail::equal_sign<Char>();
+ while (*p != nullptr)
+ {
+ if (std::equal(st1.begin(), st1.end(), *p))
+ return 1u;
+ p++;
+ }
+ return 0u;
+ }
+ void erase(const string_type & id)
+ {
+ implementation_type::reset(id);
+ this->reload();
+ }
+ std::pair<iterator,bool> emplace(const string_type & id, const string_type & value)
+ {
+ auto f = find(id);
+ if (f == end())
+ {
+ implementation_type::set(id, value);
+ this->reload();
+ return std::pair<iterator, bool>(find(id), true);
+ }
+ else
+ return std::pair<iterator, bool>(f, false);
+ }
+ using implementation_type::implementation_type;
+ using implementation_type::operator=;
+ using native_handle_type = typename implementation_type::native_handle_type;
+ using implementation_type::native_handle;
+ //copy ctor if impl is copy-constructible
+ bool empty()
+ {
+ return *this->_env_impl == nullptr;
+ }
+ std::size_t size() const
+ {
+ return (_get_end() - this->_env_impl);
+ }
+ void clear()
+ {
+ std::vector<string_type> names;
+ names.resize(size());
+ std::transform(cbegin(), cend(), names.begin(), [](const const_entry_type & cet){return cet.get_name();});
+
+ for (auto & nm : names)
+ implementation_type::reset(nm);
+
+ this->reload();
+ }
+
+ entry_type at( const string_type& key )
+ {
+ auto f = find(key);
+ if (f== end())
+ throw std::out_of_range(key + " not found");
+ return *f;
+ }
+ const_entry_type at( const string_type& key ) const
+ {
+ auto f = find(key);
+ if (f== end())
+ throw std::out_of_range(key + " not found");
+ return *f;
+ }
+ entry_type operator[](const string_type & key)
+ {
+ auto p = find(key);
+ if (p != end())
+ return *p;
+
+ return entry_type(string_type(key), *this);
+ }
+};
+#endif
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+/**Template representation of environments. It takes a character type (`char` or `wchar_t`)
+ * as template parameter to implement the environment
+ */
+template<typename Char>
+class basic_environment
+{
+
+public:
+ typedef std::basic_string<Char> string_type;
+ typedef boost::transform_iterator< entry_maker, Char**> iterator ;
+ typedef boost::transform_iterator<const_entry_maker, Char**> const_iterator ;
+ typedef std::size_t size_type ;
+
+ iterator begin() ; ///<Returns an iterator to the beginning
+ const_iterator begin() const ; ///<Returns an iterator to the beginning
+ const_iterator cbegin() const ; ///<Returns an iterator to the beginning
+
+ iterator end() ; ///<Returns an iterator to the end
+ const_iterator end() const; ///<Returns an iterator to the end
+ const_iterator cend() const; ///<Returns an iterator to the end
+
+ iterator find( const string_type& key ); ///<Find a variable by its name
+ const_iterator find( const string_type& key ) const; ///<Find a variable by its name
+
+ std::size_t count(const string_type & st) const; ///<Number of variables
+ void erase(const string_type & id); ///<Erase variable by id.
+ ///Emplace an environment variable.
+ std::pair<iterator,bool> emplace(const string_type & id, const string_type & value);
+
+ ///Default constructor
+ basic_environment();
+ ///Copy constructor.
+ basic_environment(const basic_environment & );
+ ///Move constructor.
+ basic_environment(basic_environment && );
+
+ ///Copy assignment.
+ basic_environment& operator=(const basic_environment & );
+ ///Move assignment.
+ basic_environment& operator=(basic_environment && );
+
+ typedef typename detail::implementation_type::native_handle_type native_handle;
+
+ ///Check if environment has entries.
+ bool empty();
+ ///Get the number of variables.
+ std::size_t size() const;
+ ///Clear the environment. @attention Use with care, passed environment cannot be empty.
+ void clear();
+ ///Get the entry with the key. Throws if it does not exist.
+ entry_type at( const string_type& key );
+ ///Get the entry with the key. Throws if it does not exist.
+ const_entry_type at( const string_type& key ) const;
+ ///Get the entry with the given key. It creates the entry if it doesn't exist.
+ entry_type operator[](const string_type & key);
+
+ /**Proxy class used for read access to members by [] or .at()
+ * @attention Holds a reference to the environment it was created from.
+ */
+ template<typename Char, typename Environment>
+ struct const_entry_type
+ {
+ typedef Char value_type;
+ typedef const value_type * pointer;
+ typedef std::basic_string<value_type> string_type;
+ typedef boost::iterator_range<pointer> range;
+ typedef Environment environment_t;
+
+ ///Split the entry by ";" or ":" and return it as a vector. Used by PATH.
+ std::vector<string_type> to_vector() const
+ ///Get the value as string.
+ string_type to_string() const
+ ///Get the name of this entry.
+ string_type get_name() const {return string_type(_name.begin(), _name.end());}
+ ///Copy Constructor
+ const_entry(const const_entry&) = default;
+ ///Move Constructor
+ const_entry& operator=(const const_entry&) = default;
+ ///Check if the entry is empty.
+ bool empty() const;
+ };
+
+ /**Proxy class used for read and write access to members by [] or .at()
+ * @attention Holds a reference to the environment it was created from.
+ */
+ template<typename Char, typename Environment>
+ struct entry_type
+ {
+
+ typedef Char value_type;
+ typedef const value_type * pointer;
+ typedef std::basic_string<value_type> string_type;
+ typedef boost::iterator_range<pointer> range;
+ typedef Environment environment_t;
+
+ ///Split the entry by ";" or ":" and return it as a vector. Used by PATH.
+ std::vector<string_type> to_vector() const
+ ///Get the value as string.
+ string_type to_string() const
+ ///Get the name of this entry.
+ string_type get_name() const {return string_type(_name.begin(), _name.end());}
+ ///Copy Constructor
+ entry(const entry&) = default;
+ ///Move Constructor
+ entry& operator=(const entry&) = default;
+ ///Check if the entry is empty.
+ bool empty() const;
+
+ ///Assign a string to the value
+ void assign(const string_type &value);
+ ///Assign a set of strings to the entry; they will be seperated by ';' or ':'.
+ void assign(const std::vector<string_type> &value);
+ ///Append a string to the end of the entry, it will seperated by ';' or ':'.
+ void append(const string_type &value);
+ ///Reset the value
+ void clear();
+ ///Assign a string to the entry.
+ entry &operator=(const string_type & value);
+ ///Assign a set of strings to the entry; they will be seperated by ';' or ':'.
+ entry &operator=(const std::vector<string_type> & value);
+ ///Append a string to the end of the entry, it will seperated by ';' or ':'.
+ entry &operator+=(const string_type & value);
+ };
+
+};
+
+/**Template representation of the environment of this process. It takes a template
+ * as template parameter to implement the environment. All instances of this class
+ * refer to the same environment, but might not get updated if another one makes changes.
+ */
+template<typename Char>
+class basic_native_environment
+{
+
+public:
+ typedef std::basic_string<Char> string_type;
+ typedef boost::transform_iterator< entry_maker, Char**> iterator ;
+ typedef boost::transform_iterator<const_entry_maker, Char**> const_iterator ;
+ typedef std::size_t size_type ;
+
+ iterator begin() ; ///<Returns an iterator to the beginning
+ const_iterator begin() const ; ///<Returns an iterator to the beginning
+ const_iterator cbegin() const ; ///<Returns an iterator to the beginning
+
+ iterator end() ; ///<Returns an iterator to the end
+ const_iterator end() const; ///<Returns an iterator to the end
+ const_iterator cend() const; ///<Returns an iterator to the end
+
+ iterator find( const string_type& key ); ///<Find a variable by its name
+ const_iterator find( const string_type& key ) const; ///<Find a variable by its name
+
+ std::size_t count(const string_type & st) const; ///<Number of variables
+ void erase(const string_type & id); ///<Erase variable by id.
+ ///Emplace an environment variable.
+ std::pair<iterator,bool> emplace(const string_type & id, const string_type & value);
+
+ ///Default constructor
+ basic_native_environment();
+ ///Move constructor.
+ basic_native_environment(basic_native_environment && );
+ ///Move assignment.
+ basic_native_environment& operator=(basic_native_environment && );
+
+ typedef typename detail::implementation_type::native_handle_type native_handle;
+
+ ///Check if environment has entries.
+ bool empty();
+ ///Get the number of variables.
+ std::size_t size() const;
+ ///Get the entry with the key. Throws if it does not exist.
+ entry_type at( const string_type& key );
+ ///Get the entry with the key. Throws if it does not exist.
+ const_entry_type at( const string_type& key ) const;
+ ///Get the entry with the given key. It creates the entry if it doesn't exist.
+ entry_type operator[](const string_type & key);
+
+ /**Proxy class used for read access to members by [] or .at()
+ * @attention Holds a reference to the environment it was created from.
+ */
+ template<typename Char, typename Environment>
+ struct const_entry_type
+ {
+ typedef Char value_type;
+ typedef const value_type * pointer;
+ typedef std::basic_string<value_type> string_type;
+ typedef boost::iterator_range<pointer> range;
+ typedef Environment environment_t;
+
+ ///Split the entry by ";" or ":" and return it as a vector. Used by PATH.
+ std::vector<string_type> to_vector() const
+ ///Get the value as string.
+ string_type to_string() const
+ ///Get the name of this entry.
+ string_type get_name() const {return string_type(_name.begin(), _name.end());}
+ ///Copy Constructor
+ const_entry(const const_entry&) = default;
+ ///Move Constructor
+ const_entry& operator=(const const_entry&) = default;
+ ///Check if the entry is empty.
+ bool empty() const;
+ };
+
+ /**Proxy class used for read and write access to members by [] or .at()
+ * @attention Holds a reference to the environment it was created from.
+ */
+ template<typename Char, typename Environment>
+ struct entry_type
+ {
+
+ typedef Char value_type;
+ typedef const value_type * pointer;
+ typedef std::basic_string<value_type> string_type;
+ typedef boost::iterator_range<pointer> range;
+ typedef Environment environment_t;
+
+ ///Split the entry by ";" or ":" and return it as a vector. Used by PATH.
+ std::vector<string_type> to_vector() const
+ ///Get the value as string.
+ string_type to_string() const
+ ///Get the name of this entry.
+ string_type get_name() const {return string_type(_name.begin(), _name.end());}
+ ///Copy Constructor
+ entry(const entry&) = default;
+ ///Move Constructor
+ entry& operator=(const entry&) = default;
+ ///Check if the entry is empty.
+ bool empty() const;
+
+ ///Assign a string to the value
+ void assign(const string_type &value);
+ ///Assign a set of strings to the entry; they will be seperated by ';' or ':'.
+ void assign(const std::vector<string_type> &value);
+ ///Append a string to the end of the entry, it will seperated by ';' or ':'.
+ void append(const string_type &value);
+ ///Reset the value
+ void clear();
+ ///Assign a string to the entry.
+ entry &operator=(const string_type & value);
+ ///Assign a set of strings to the entry; they will be seperated by ';' or ':'.
+ entry &operator=(const std::vector<string_type> & value);
+ ///Append a string to the end of the entry, it will seperated by ';' or ':'.
+ entry &operator+=(const string_type & value);
+ };
+
+};
+
+#endif
+
+///Definition of the environment for the current process.
+template<typename Char>
+class basic_native_environment : public basic_environment_impl<Char, detail::api::native_environment_impl>
+{
+public:
+ using base_type = basic_environment_impl<Char, detail::api::native_environment_impl>;
+ using base_type::base_type;
+ using base_type::operator=;
+};
+
+///Type definition to hold a seperate environment.
+template<typename Char>
+class basic_environment : public basic_environment_impl<Char, detail::api::basic_environment_impl>
+{
+public:
+ using base_type = basic_environment_impl<Char, detail::api::basic_environment_impl>;
+ using base_type::base_type;
+ using base_type::operator=;
+};
+
+
+
+///Definition of the environment for the current process.
+typedef basic_native_environment<char> native_environment;
+///Definition of the environment for the current process.
+typedef basic_native_environment<wchar_t> wnative_environment;
+
+///Type definition to hold a seperate environment.
+typedef basic_environment<char> environment;
+///Type definition to hold a seperate environment.
+typedef basic_environment<wchar_t> wenvironment;
+
+}
+
+///Namespace containing information of the calling process.
+namespace this_process
+{
+
+///Definition of the native handle type.
+typedef ::boost::process::detail::api::native_handle_t native_handle_type;
+
+///Definition of the environment for this process.
+using ::boost::process::native_environment;
+///Definition of the environment for this process.
+using ::boost::process::wnative_environment;
+
+///Get the process id of the current process.
+inline int get_id() { return ::boost::process::detail::api::get_id();}
+///Get the native handle of the current process.
+inline native_handle_type native_handle() { return ::boost::process::detail::api::native_handle();}
+///Get the enviroment of the current process.
+inline native_environment environment() { return ::boost::process:: native_environment(); }
+///Get the enviroment of the current process.
+inline wnative_environment wenvironment() { return ::boost::process::wnative_environment(); }
+///Get the path environment variable of the current process runs.
+inline std::vector<boost::filesystem::path> path()
+{
+#if defined(BOOST_WINDOWS_API)
+ const ::boost::process::wnative_environment ne{};
+ typedef typename ::boost::process::wnative_environment::const_entry_type value_type;
+ const auto id = L"PATH";
+#else
+ const ::boost::process::native_environment ne{};
+ typedef typename ::boost::process::native_environment::const_entry_type value_type;
+ const auto id = "PATH";
+#endif
+
+ auto itr = std::find_if(ne.cbegin(), ne.cend(),
+ [&](const value_type & e)
+ {return id == ::boost::to_upper_copy(e.get_name(), ::boost::process::detail::process_locale());});
+
+ if (itr == ne.cend())
+ return {};
+
+ auto vec = itr->to_vector();
+
+ std::vector<boost::filesystem::path> val;
+ val.resize(vec.size());
+
+ std::copy(vec.begin(), vec.end(), val.begin());
+
+ return val;
+}
+}
+}
+#endif /* INCLUDE_BOOST_PROCESS_DETAIL_ENVIRONMENT_HPP_ */
diff --git a/boost/process/error.hpp b/boost/process/error.hpp
new file mode 100644
index 0000000000..f70cce6c83
--- /dev/null
+++ b/boost/process/error.hpp
@@ -0,0 +1,211 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_DETAIL_ERROR_HPP
+#define BOOST_PROCESS_DETAIL_ERROR_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/traits.hpp>
+
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/handler.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/handler.hpp>
+#endif
+
+#include <system_error>
+
+#include <type_traits>
+#include <boost/fusion/algorithm/query/find_if.hpp>
+#include <boost/fusion/sequence/intrinsic/begin.hpp>
+#include <boost/fusion/sequence/intrinsic/end.hpp>
+#include <boost/fusion/container/vector/convert.hpp>
+#include <boost/fusion/iterator/deref.hpp>
+#include <boost/fusion/sequence/comparison/equal_to.hpp>
+#include <boost/fusion/container/set/convert.hpp>
+#include <boost/type_index.hpp>
+
+/** \file boost/process/error.hpp
+ *
+ * Header which provides the error properties. It allows to explicitly set the error handling, the properties are:
+ *
+\xmlonly
+<programlisting>
+namespace boost {
+ namespace process {
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::ignore_error">ignore_error</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::throw_on_error">throw_on_error</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::error">error</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::error_ref">error_ref</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::error_code">error_code</globalname>;
+ }
+}
+</programlisting>
+\endxmlonly
+ * For error there are two aliases: error_ref and error_code
+ */
+
+namespace boost { namespace process {
+
+namespace detail {
+
+struct throw_on_error_ : ::boost::process::detail::api::handler_base_ext
+{
+ constexpr throw_on_error_() {};
+
+ template <class Executor>
+ void on_error(Executor&, const std::error_code & ec) const
+ {
+ throw process_error(ec, "process creation failed");
+ }
+
+ const throw_on_error_ &operator()() const {return *this;}
+};
+
+struct ignore_error_ : ::boost::process::detail::api::handler_base_ext
+{
+ constexpr ignore_error_() {};
+};
+
+struct set_on_error : ::boost::process::detail::api::handler_base_ext
+{
+ set_on_error(const set_on_error&) = default;
+ explicit set_on_error(std::error_code &ec) : ec_(ec) {}
+
+ template <class Executor>
+ void on_error(Executor&, const std::error_code & ec) const
+ {
+ ec_ = ec;
+ }
+
+private:
+ std::error_code &ec_;
+};
+
+struct error_
+{
+ constexpr error_() {}
+ set_on_error operator()(std::error_code &ec) const {return set_on_error(ec);}
+ set_on_error operator= (std::error_code &ec) const {return set_on_error(ec);}
+
+};
+
+
+template<typename T>
+struct is_error_handler : std::false_type {};
+
+template<> struct is_error_handler<set_on_error> : std::true_type {};
+template<> struct is_error_handler<throw_on_error_> : std::true_type {};
+template<> struct is_error_handler<ignore_error_> : std::true_type {};
+
+
+
+template<typename Iterator, typename End>
+struct has_error_handler_impl
+{
+ typedef typename boost::fusion::result_of::deref<Iterator>::type ref_type;
+ typedef typename std::remove_reference<ref_type>::type res_type_;
+ typedef typename std::remove_cv<res_type_>::type res_type;
+ typedef typename is_error_handler<res_type>::type cond;
+
+ typedef typename boost::fusion::result_of::next<Iterator>::type next_itr;
+ typedef typename has_error_handler_impl<next_itr, End>::type next;
+
+ typedef typename boost::mpl::or_<cond, next>::type type;
+};
+
+template<typename Iterator>
+struct has_error_handler_impl<Iterator, Iterator>
+{
+ typedef boost::mpl::false_ type;
+};
+
+
+template<typename Sequence>
+struct has_error_handler
+{
+ typedef typename boost::fusion::result_of::as_vector<Sequence>::type vector_type;
+
+ typedef typename has_error_handler_impl<
+ typename boost::fusion::result_of::begin<vector_type>::type,
+ typename boost::fusion::result_of::end< vector_type>::type
+ >::type type;
+};
+
+template<typename Sequence>
+struct has_ignore_error
+{
+ typedef typename boost::fusion::result_of::as_set<Sequence>::type set_type;
+ typedef typename boost::fusion::result_of::has_key<set_type, ignore_error_>::type type1;
+ typedef typename boost::fusion::result_of::has_key<set_type, ignore_error_&>::type type2;
+ typedef typename boost::fusion::result_of::has_key<set_type, const ignore_error_&>::type type3;
+ typedef typename boost::mpl::or_<type1,type2, type3>::type type;
+};
+
+struct error_builder
+{
+ std::error_code *err;
+ typedef set_on_error result_type;
+ set_on_error get_initializer() {return set_on_error(*err);};
+ void operator()(std::error_code & ec) {err = &ec;};
+};
+
+template<>
+struct initializer_tag<std::error_code>
+{
+ typedef error_tag type;
+};
+
+
+template<>
+struct initializer_builder<error_tag>
+{
+ typedef error_builder type;
+};
+
+}
+/**The ignore_error property will disable any error handling. This can be useful
+on linux, where error handling will require a pipe.*/
+constexpr boost::process::detail::ignore_error_ ignore_error;
+/**The throw_on_error property will enable the exception when launching a process.
+It is unnecessary by default, but may be used, when an additional error_code is provided.*/
+constexpr boost::process::detail::throw_on_error_ throw_on_error;
+/**
+The error property will set the executor to handle any errors by setting an
+[std::error_code](http://en.cppreference.com/w/cpp/error/error_code).
+
+\code{.cpp}
+std::error_code ec;
+system("gcc", error(ec));
+\endcode
+
+The following syntax is valid:
+
+\code{.cpp}
+error(ec);
+error=ec;
+\endcode
+
+The overload version is achieved by just passing an object of
+ [std::error_code](http://en.cppreference.com/w/cpp/error/error_code) to the function.
+
+
+ */
+constexpr boost::process::detail::error_ error;
+///Alias for \xmlonly <globalname alt="boost::process::error">error</globalname> \endxmlonly .
+constexpr boost::process::detail::error_ error_ref;
+///Alias for \xmlonly <globalname alt="boost::process::error">error</globalname> \endxmlonly .
+constexpr boost::process::detail::error_ error_code;
+
+
+}}
+
+#endif
diff --git a/boost/process/exception.hpp b/boost/process/exception.hpp
new file mode 100644
index 0000000000..1bb391117a
--- /dev/null
+++ b/boost/process/exception.hpp
@@ -0,0 +1,30 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_EXCEPTION_HPP_
+#define BOOST_PROCESS_EXCEPTION_HPP_
+
+#include <system_error>
+
+namespace boost
+{
+namespace process
+{
+///The exception usually thrown by boost.process.
+/** It merely inherits [std::system_error](http://en.cppreference.com/w/cpp/error/system_error)
+ * but can then be distinguished in the catch-block from other system errors.
+ *
+ */
+struct process_error : std::system_error
+{
+ using std::system_error::system_error;
+};
+
+}
+}
+
+
+
+#endif /* BOOST_PROCESS_EXCEPTION_HPP_ */
diff --git a/boost/process/exe.hpp b/boost/process/exe.hpp
new file mode 100644
index 0000000000..04a63bc754
--- /dev/null
+++ b/boost/process/exe.hpp
@@ -0,0 +1,79 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_EXE_HPP
+#define BOOST_PROCESS_EXE_HPP
+
+#include <boost/process/detail/basic_cmd.hpp>
+
+/** \file boost/process/exe.hpp
+ *
+ * Header which provides the exe property.
+\xmlonly
+<programlisting>
+namespace boost {
+ namespace process {
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::exe">exe</globalname>;
+ }
+}
+</programlisting>
+\endxmlonly
+ */
+namespace boost { namespace process { namespace detail {
+
+struct exe_
+{
+ template<typename Char>
+ inline exe_setter_<Char> operator()(const Char *s) const
+ {
+ return exe_setter_<Char>(s);
+ }
+ template<typename Char>
+ inline exe_setter_<Char> operator= (const Char *s) const
+ {
+ return exe_setter_<Char>(s);
+ }
+
+ template<typename Char>
+ inline exe_setter_<Char> operator()(const std::basic_string<Char> &s) const
+ {
+ return exe_setter_<Char>(s);
+ }
+ template<typename Char>
+ inline exe_setter_<Char> operator= (const std::basic_string<Char> &s) const
+ {
+ return exe_setter_<Char>(s);
+ }
+};
+
+}
+
+/** The exe property allows to explicitly set the executable.
+
+The overload form applies when to the first, when several strings are passed to a launching
+function.
+
+The following expressions are valid, with `value` being either a C-String or
+a `std::basic_string` with `char` or `wchar_t` or a `boost::filesystem::path`.
+
+\code{.cpp}
+exe="value";
+exe(value);
+\endcode
+
+The property can only be used for assignments.
+
+
+ */
+constexpr boost::process::detail::exe_ exe{};
+
+}}
+
+#endif
diff --git a/boost/process/extend.hpp b/boost/process/extend.hpp
new file mode 100644
index 0000000000..7496f30f16
--- /dev/null
+++ b/boost/process/extend.hpp
@@ -0,0 +1,339 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_EXTENSIONS_HPP_
+#define BOOST_PROCESS_EXTENSIONS_HPP_
+
+#include <boost/process/detail/handler.hpp>
+
+#if defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/executor.hpp>
+#include <boost/process/detail/windows/async_handler.hpp>
+#include <boost/process/detail/windows/asio_fwd.hpp>
+#else
+#include <boost/process/detail/posix/executor.hpp>
+#include <boost/process/detail/posix/async_handler.hpp>
+#include <boost/process/detail/posix/asio_fwd.hpp>
+#endif
+
+
+/** \file boost/process/extend.hpp
+ *
+ * This header which provides the types and functions provided for custom extensions.
+ *
+ * \xmlonly
+ Please refer to the <link linkend="boost_process.extend">tutorial</link> for more details.
+ \endxmlonly
+ */
+
+
+namespace boost {
+namespace process {
+namespace detail {
+template<typename Tuple>
+inline asio::io_service& get_io_service(const Tuple & tup);
+}
+
+
+///Namespace for extensions \attention This is experimental.
+namespace extend {
+
+#if defined(BOOST_WINDOWS_API)
+
+template<typename Char, typename Sequence>
+using windows_executor = ::boost::process::detail::windows::executor<Char, Sequence>;
+template<typename Sequence>
+struct posix_executor;
+
+#elif defined(BOOST_POSIX_API)
+
+template<typename Sequence>
+using posix_executor = ::boost::process::detail::posix::executor<Sequence>;
+template<typename Char, typename Sequence>
+struct windows_executor;
+
+#endif
+
+using ::boost::process::detail::handler;
+using ::boost::process::detail::api::require_io_service;
+using ::boost::process::detail::api::async_handler;
+using ::boost::process::detail::get_io_service;
+using ::boost::process::detail::get_last_error;
+using ::boost::process::detail::throw_last_error;
+
+///This handler is invoked before the process in launched, to setup parameters. The required signature is `void(Exec &)`, where `Exec` is a template parameter.
+constexpr boost::process::detail::make_handler_t<boost::process::detail::on_setup_> on_setup;
+///This handler is invoked if an error occured. The required signature is `void(auto & exec, const std::error_code&)`, where `Exec` is a template parameter.
+constexpr boost::process::detail::make_handler_t<boost::process::detail::on_error_> on_error;
+///This handler is invoked if launching the process has succeeded. The required signature is `void(auto & exec)`, where `Exec` is a template parameter.
+constexpr boost::process::detail::make_handler_t<boost::process::detail::on_success_> on_success;
+
+#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
+///This handler is invoked if the fork failed. The required signature is `void(auto & exec)`, where `Exec` is a template parameter. \note Only available on posix.
+constexpr ::boost::process::detail::make_handler_t<::boost::process::detail::posix::on_fork_error_ > on_fork_error;
+///This handler is invoked if the fork succeeded. The required signature is `void(Exec &)`, where `Exec` is a template parameter. \note Only available on posix.
+constexpr ::boost::process::detail::make_handler_t<::boost::process::detail::posix::on_exec_setup_ > on_exec_setup;
+///This handler is invoked if the exec call errored. The required signature is `void(auto & exec)`, where `Exec` is a template parameter. \note Only available on posix.
+constexpr ::boost::process::detail::make_handler_t<::boost::process::detail::posix::on_exec_error_ > on_exec_error;
+#endif
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+///Helper function to get the last error code system-independent
+inline std::error_code get_last_error();
+
+///Helper function to get and throw the last system error.
+/// \throws boost::process::process_error
+/// \param msg A message to add to the error code.
+inline void throw_last_error(const std::string & msg);
+///\overload void throw_last_error(const std::string & msg)
+inline void throw_last_error();
+
+
+/** This function gets the io_service from the initializer sequence.
+ *
+ * \attention Yields a compile-time error if no `io_service` is provided.
+ * \param seq The Sequence of the initializer.
+ */
+template<typename Sequence>
+inline asio::io_service& get_io_service(const Sequence & seq);
+
+/** This class is the base for every initializer, to be used for extensions.
+ *
+ * The usage is done through compile-time polymorphism, so that the required
+ * functions can be overloaded.
+ *
+ * \note None of the function need to be `const`.
+ *
+ */
+struct handler
+{
+ ///This function is invoked before the process launch. \note It is not required to be const.
+ template <class Executor>
+ void on_setup(Executor&) const {}
+
+ /** This function is invoked if an error occured while trying to launch the process.
+ * \note It is not required to be const.
+ */
+ template <class Executor>
+ void on_error(Executor&, const std::error_code &) const {}
+
+ /** This function is invoked if the process was successfully launched.
+ * \note It is not required to be const.
+ */
+ template <class Executor>
+ void on_success(Executor&) const {}
+
+ /**This function is invoked if an error occured during the call of `fork`.
+ * \note This function will only be called on posix.
+ */
+ template<typename Executor>
+ void on_fork_error (Executor &, const std::error_code&) const {}
+
+ /**This function is invoked if the call of `fork` was successful, before
+ * calling `execve`.
+ * \note This function will only be called on posix.
+ * \attention It will be invoked from the new process.
+ */
+ template<typename Executor>
+ void on_exec_setup (Executor &) const {}
+
+ /**This function is invoked if the call of `execve` failed.
+ * \note This function will only be called on posix.
+ * \attention It will be invoked from the new process.
+ */
+ template<typename Executor>
+ void on_exec_error (Executor &, const std::error_code&) const {}
+
+};
+
+
+/** Inheriting the class will tell the launching process that an `io_service` is
+ * needed. This should always be used when \ref get_io_service is used.
+ *
+ */
+struct require_io_service {};
+/** Inheriting this class will tell the launching function, that an event handler
+ * shall be invoked when the process exits. This automatically does also inherit
+ * \ref require_io_service.
+ *
+ * You must add the following function to your implementation:
+ *
+ \code{.cpp}
+template<typename Executor>
+std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec)
+{
+ auto handler = this->handler;
+ return [handler](int exit_code, const std::error_code & ec)
+ {
+ handler(static_cast<int>(exit_code), ec);
+ };
+
+}
+ \endcode
+
+ The callback will be obtained by calling this function on setup and it will be
+ invoked when the process exits.
+
+ *
+ * \warning Cannot be used with \ref boost::process::spawn
+ */
+struct async_handler : handler, require_io_service
+{
+
+};
+
+///The posix executor type.
+/** This type represents the posix executor and can be used for overloading in a custom handler.
+ * \note It is an alias for the implementation on posix, and a forward-declaration on windows.
+ *
+ * \tparam Sequence The used initializer-sequence, it is fulfills the boost.fusion [sequence](http://www.boost.org/doc/libs/master/libs/fusion/doc/html/fusion/sequence.html) concept.
+
+
+\xmlonly
+As information for extension development, here is the structure of the process launching (in pseudo-code and uml)
+<xi:include href="posix_pseudocode.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<mediaobject>
+<caption>
+<para>The sequence if when no error occurs.</para>
+</caption>
+<imageobject>
+<imagedata fileref="boost_process/posix_success.svg"/>
+</imageobject>
+</mediaobject>
+
+<mediaobject>
+<caption>
+<para>The sequence if the execution fails.</para>
+</caption>
+<imageobject>
+<imagedata fileref="boost_process/posix_exec_err.svg"/>
+</imageobject>
+</mediaobject>
+
+<mediaobject>
+<caption>
+<para>The sequence if the fork fails.</para>
+</caption>
+<imageobject>
+<imagedata fileref="boost_process/posix_fork_err.svg"/>
+</imageobject>
+</mediaobject>
+
+\endxmlonly
+
+
+\note Error handling if execve fails is done through a pipe, unless \ref ignore_error is used.
+
+ */
+template<typename Sequence>
+struct posix_executor
+{
+ ///A reference to the actual initializer-sequence
+ Sequence & seq;
+ ///A pointer to the name of the executable.
+ const char * exe = nullptr;
+ ///A pointer to the argument-vector.
+ char *const* cmd_line = nullptr;
+ ///A pointer to the environment variables, as default it is set to [environ](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html)
+ char **env = ::environ;
+ ///The pid of the process - it will be -1 before invoking [fork](http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html), and after forking either 0 for the new process or a positive value if in the current process. */
+ pid_t pid = -1;
+ ///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_service` and \ref child.
+ std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active);
+
+ ///This function returns a const reference to the error state of the executor.
+ const std::error_code & error() const;
+
+ ///This function can be used to report an error to the executor. This will be handled according to the configuration of the executor, i.e. it
+ /// might throw an exception. \note This is the required way to handle errors in initializers.
+ void set_error(const std::error_code &ec, const std::string &msg);
+ ///\overload void set_error(const std::error_code &ec, const std::string &msg);
+ void set_error(const std::error_code &ec, const char* msg);
+};
+
+///The windows executor type.
+/** This type represents the posix executor and can be used for overloading in a custom handler.
+ *
+ * \note It is an alias for the implementation on posix, and a forward-declaration on windows.
+ * \tparam Sequence The used initializer-sequence, it is fulfills the boost.fusion [sequence](http://www.boost.org/doc/libs/master/libs/fusion/doc/html/fusion/sequence.html) concept.
+ * \tparam Char The used char-type, either `char` or `wchar_t`.
+ *
+
+\xmlonly
+As information for extension development, here is the structure of the process launching (in pseudo-code and uml)<xi:include href="windows_pseudocode.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+<mediaobject>
+<caption>
+<para>The sequence for windows process creation.</para>
+</caption>
+<imageobject>
+<imagedata fileref="boost_process/windows_exec.svg"/>
+</imageobject>
+</mediaobject>
+\endxmlonly
+
+ */
+
+template<typename Char, typename Sequence>
+struct windows_executor
+{
+ ///A reference to the actual initializer-sequence
+ Sequence & seq;
+
+ ///A pointer to the name of the executable. It's null by default.
+ const Char * exe = nullptr;
+ ///A pointer to the argument-vector. Must be set by some initializer.
+ char Char* cmd_line = nullptr;
+ ///A pointer to the environment variables. It's null by default.
+ char Char* env = nullptr;
+ ///A pointer to the working directory. It's null by default.
+ const Char * work_dir = nullptr;
+
+ ///A pointer to the process-attributes of type [SECURITY_ATTRIBUTES](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379560.aspx). It's null by default.
+ ::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ proc_attrs = nullptr;
+ ///A pointer to the thread-attributes of type [SECURITY_ATTRIBUTES](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379560.aspx). It' null by default.
+ ::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ thread_attrs = nullptr;
+ ///A logical bool value setting whether handles shall be inherited or not.
+ ::boost::detail::winapi::BOOL_ inherit_handles = false;
+
+ ///The element holding the process-information after process creation. The type is [PROCESS_INFORMATION](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684873.aspx)
+ ::boost::detail::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
+
+
+ ///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_service` and \ref child.
+ std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active);
+
+ ///This function returns a const reference to the error state of the executor.
+ const std::error_code & error() const;
+
+ ///This function can be used to report an error to the executor. This will be handled according to the configuration of the executor, i.e. it
+ /// might throw an exception. \note This is the required way to handle errors in initializers.
+ void set_error(const std::error_code &ec, const std::string &msg);
+ ///\overload void set_error(const std::error_code &ec, const std::string &msg);
+ void set_error(const std::error_code &ec, const char* msg);
+
+ ///The creation flags of the process
+ ::boost::detail::winapi::DWORD_ creation_flags;
+ ///The type of the [startup-info](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331.aspx), depending on the char-type.
+ typedef typename detail::startup_info<Char>::type startup_info_t;
+ ///The type of the [extended startup-info](https://msdn.microsoft.com/de-de/library/windows/desktop/ms686329.aspx), depending the char-type; only defined with winapi-version equal or higher than 6.
+ typedef typename detail::startup_info_ex<Char>::type startup_info_ex_t;
+ ///This function switches the information, so that the extended structure is used. \note It's only defined with winapi-version equal or higher than 6.
+ void set_startup_info_ex();
+ ///This element is an instance or a reference (if \ref startup_info_ex exists) to the [startup-info](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331.aspx) for the process.
+ startup_info_t startup_info;
+ ///This element is the instance of the [extended startup-info](https://msdn.microsoft.com/de-de/library/windows/desktop/ms686329.aspx). It is only available with a winapi-version equal or highter than 6.
+ startup_info_ex_t startup_info_ex;
+};
+
+
+
+#endif
+
+}
+}
+}
+
+#endif
diff --git a/boost/process/group.hpp b/boost/process/group.hpp
new file mode 100644
index 0000000000..b46f064475
--- /dev/null
+++ b/boost/process/group.hpp
@@ -0,0 +1,228 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the 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 boost/process/group.hpp
+ *
+ * Defines a group process class.
+ * For additional information see the platform specific implementations:
+ *
+ * - [windows - job object](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684161.aspx)
+ * - [posix - process group](http://pubs.opengroup.org/onlinepubs/009695399/functions/setpgid.html)
+ *
+ */
+
+#ifndef BOOST_PROCESS_GROUP_HPP
+#define BOOST_PROCESS_GROUP_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/child.hpp>
+#include <chrono>
+#include <memory>
+
+#include <boost/none.hpp>
+#include <atomic>
+
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/group_handle.hpp>
+#include <boost/process/detail/posix/group_ref.hpp>
+#include <boost/process/detail/posix/wait_group.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/group_handle.hpp>
+#include <boost/process/detail/windows/group_ref.hpp>
+#include <boost/process/detail/windows/wait_group.hpp>
+#endif
+
+namespace boost {
+
+namespace process {
+
+namespace detail {
+ struct group_builder;
+}
+
+/**
+ * Represents a process group.
+ *
+ * Groups are movable but non-copyable. The destructor
+ * automatically closes handles to the group process.
+ *
+ * The group will have the same interface as std::thread.
+ *
+ * \note If the destructor is called without a previous detach or wait, the group will be terminated.
+ *
+ * \attention If a default-constructed group is used before being used in a process launch, the behaviour is undefined.
+ *
+ * \attention Waiting for groups is currently broken on windows and will most likely result in a dead-lock.
+ */
+class group
+{
+ ::boost::process::detail::api::group_handle _group_handle;
+ bool _attached = true;
+public:
+ typedef ::boost::process::detail::api::group_handle group_handle;
+ ///Native representation of the handle.
+ typedef group_handle::handle_t native_handle_t;
+ explicit group(group_handle &&ch) : _group_handle(std::move(ch)) {}
+ ///Construct the group from a native_handle
+ explicit group(native_handle_t & handle) : _group_handle(handle) {};
+ group(const group&) = delete;
+ ///Move constructor
+ group(group && lhs)
+ : _group_handle(std::move(lhs._group_handle)),
+ _attached (lhs._attached)
+ {
+ lhs._attached = false;
+ }
+ ///Default constructor
+ group() = default;
+ group& operator=(const group&) = delete;
+ ///Move assign
+ group& operator=(group && lhs)
+ {
+ _group_handle= std::move(lhs._group_handle);
+ _attached = lhs._attached;
+
+ return *this;
+ };
+
+ ///Detach the group
+ void detach() {_attached = false; }
+
+ /** Join the child. This just calls wait, but that way the naming is similar to std::thread */
+ void join() {wait();}
+ /** Check if the child is joinable. */
+ bool joinable() {return _attached;}
+
+ /** Destructor
+ *
+ * \note If the destructor is called without a previous detach or wait, the group will be terminated.
+ *
+ */
+ ~group()
+ {
+ std::error_code ec;
+ if ( _attached && valid())
+ terminate(ec);
+ }
+
+ ///Obtain the native handle of the group.
+ native_handle_t native_handle() const { return _group_handle.handle(); }
+
+ ///Wait for the process group to exit.
+ void wait()
+ {
+ boost::process::detail::api::wait(_group_handle);
+ }
+ ///\overload void wait()
+ void wait(std::error_code & ec) noexcept
+ {
+ boost::process::detail::api::wait(_group_handle, ec);
+ }
+ /** Wait for the process group to exit for period of time.
+ * \return True if all child processes exited while waiting.*/
+ template< class Rep, class Period >
+ bool wait_for (const std::chrono::duration<Rep, Period>& rel_time)
+ {
+ return boost::process::detail::api::wait_for(_group_handle, rel_time);
+ }
+
+ /** \overload bool wait_for(const std::chrono::duration<Rep, Period>& timeout_time ) */
+ template< class Rep, class Period >
+ bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept
+ {
+ return boost::process::detail::api::wait_for(_group_handle, rel_time, ec);
+ }
+
+ /** Wait for the process group to exit until a point in time.
+ * \return True if all child processes exited while waiting.*/
+ template< class Clock, class Duration >
+ bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time )
+ {
+ return boost::process::detail::api::wait_until(_group_handle, timeout_time);
+ }
+ /** \overload bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time ) */
+ template< class Clock, class Duration >
+ bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, std::error_code & ec) noexcept
+ {
+ return boost::process::detail::api::wait_until(_group_handle, timeout_time, ec);
+ }
+
+ ///Check if the group has a valid handle.
+ bool valid() const
+ {
+ return _group_handle.valid();
+ }
+ ///Convenience to call valid.
+ explicit operator bool() const {return valid();}
+
+ ///Terminate the process group, i.e. all processes in the group
+ void terminate()
+ {
+ ::boost::process::detail::api::terminate(_group_handle);
+ }
+ ///\overload void terminate()
+ void terminate(std::error_code & ec) noexcept
+ {
+ ::boost::process::detail::api::terminate(_group_handle, ec);
+ }
+
+ ///Assign a child process to the group
+ void add(const child &c)
+ {
+ _group_handle.add(c.native_handle());
+ }
+ ///\overload void assign(const child & c)
+ void add(const child &c, std::error_code & ec) noexcept
+ {
+ _group_handle.add(c.native_handle(), ec);
+ }
+
+ ///Check if the child process is in the group
+ bool has(const child &c)
+ {
+ return _group_handle.has(c.native_handle());
+ }
+ ///\overload bool has(const child &)
+ bool has(const child &c, std::error_code & ec) noexcept
+ {
+ return _group_handle.has(c.native_handle(), ec);
+
+ }
+
+ friend struct detail::group_builder;
+};
+
+namespace detail
+{
+
+struct group_tag;
+struct group_builder
+{
+ group * group_p;
+
+ void operator()(group & grp) {this->group_p = &grp;};
+
+ typedef api::group_ref result_type;
+ api::group_ref get_initializer() {return api::group_ref (group_p->_group_handle);};
+};
+
+template<>
+struct initializer_tag<group>
+{
+ typedef group_tag type;
+};
+
+template<>
+struct initializer_builder<group_tag>
+{
+ typedef group_builder type;
+};
+
+}
+}}
+#endif
+
diff --git a/boost/process/io.hpp b/boost/process/io.hpp
new file mode 100644
index 0000000000..85a143ca31
--- /dev/null
+++ b/boost/process/io.hpp
@@ -0,0 +1,551 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_IO_HPP_
+#define BOOST_PROCESS_IO_HPP_
+
+#include <iosfwd>
+#include <cstdio>
+#include <functional>
+#include <utility>
+#include <boost/process/detail/config.hpp>
+#include <boost/process/pipe.hpp>
+
+#include <future>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/asio_fwd.hpp>
+#include <boost/process/detail/posix/close_in.hpp>
+#include <boost/process/detail/posix/close_out.hpp>
+#include <boost/process/detail/posix/null_in.hpp>
+#include <boost/process/detail/posix/null_out.hpp>
+#include <boost/process/detail/posix/file_in.hpp>
+#include <boost/process/detail/posix/file_out.hpp>
+#include <boost/process/detail/posix/pipe_in.hpp>
+#include <boost/process/detail/posix/pipe_out.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/asio_fwd.hpp>
+#include <boost/process/detail/windows/close_in.hpp>
+#include <boost/process/detail/windows/close_out.hpp>
+#include <boost/process/detail/windows/null_in.hpp>
+#include <boost/process/detail/windows/null_out.hpp>
+#include <boost/process/detail/windows/file_in.hpp>
+#include <boost/process/detail/windows/file_out.hpp>
+#include <boost/process/detail/windows/pipe_in.hpp>
+#include <boost/process/detail/windows/pipe_out.hpp>
+#endif
+
+/** \file boost/process/io.hpp
+ *
+ * Header which provides the io properties. It provides the following properties:
+ *
+\xmlonly
+<programlisting>
+namespace boost {
+ namespace process {
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::close">close</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::null">null</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::std_in">std_in</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::std_out">std_out</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::std_err">std_err</globalname>;
+ }
+}
+</programlisting>
+\endxmlonly
+
+\par File I/O
+
+The library allows full redirection of streams to files as shown below.
+
+\code{.cpp}
+boost::filesystem::path log = "my_log_file.txt";
+boost::filesystem::path input = "input.txt";
+boost::filesystem::path output = "output.txt";
+system("my_prog", std_out>output, std_in<input, std_err>log);
+\endcode
+
+\par Synchronous Pipe I/O
+
+Another way is to communicate through pipes.
+
+\code{.cpp}
+pstream str;
+child c("my_prog", std_out > str);
+
+int i;
+str >> i;
+\endcode
+
+Note that the pipe may also be used between several processes, like this:
+
+\code{.cpp}
+pipe p;
+child c1("nm", "a.out", std_out>p);
+child c2("c++filt", std_in<p);
+\endcode
+
+\par Asynchronous I/O
+
+Utilizing `boost.asio` asynchronous I/O is provided.
+
+\code
+boost::asio::io_service ios;
+std::future<std::string> output;
+system("ls", std_out > output, ios);
+
+auto res = fut.get();
+\endcode
+
+\note `boost/process/asnyc.hpp` must also be included for this to work.
+
+\par Closing
+
+Stream can be closed, so nothing can be read or written.
+
+\code{.cpp}
+system("foo", std_in.close());
+\endcode
+
+\par Null
+
+Streams can be redirected to null, which means, that written date will be
+discarded and read data will only contain `EOF`.
+
+\code{.cpp}
+system("b2", std_out > null);
+\endcode
+
+ *
+ */
+
+namespace boost { namespace process { namespace detail {
+
+
+template<typename T> using is_streambuf = typename std::is_same<T, boost::asio::streambuf>::type;
+template<typename T> using is_const_buffer =
+ std::integral_constant<bool,
+ std::is_same< boost::asio::const_buffer, T>::value |
+ std::is_base_of<boost::asio::const_buffer, T>::value
+ >;
+template<typename T> using is_mutable_buffer =
+ std::integral_constant<bool,
+ std::is_same< boost::asio::mutable_buffer, T>::value |
+ std::is_base_of<boost::asio::mutable_buffer, T>::value
+ >;
+
+
+struct null_t {constexpr null_t() {}};
+struct close_t;
+
+template<class>
+struct std_in_
+{
+ constexpr std_in_() {}
+
+ api::close_in close() const {return api::close_in(); }
+ api::close_in operator=(const close_t &) const {return api::close_in();}
+ api::close_in operator<(const close_t &) const {return api::close_in();}
+
+ api::null_in null() const {return api::null_in();}
+ api::null_in operator=(const null_t &) const {return api::null_in();}
+ api::null_in operator<(const null_t &) const {return api::null_in();}
+
+ api::file_in operator=(const boost::filesystem::path &p) const {return p;}
+ api::file_in operator=(const std::string & p) const {return p;}
+ api::file_in operator=(const std::wstring &p) const {return p;}
+ api::file_in operator=(const char * p) const {return p;}
+ api::file_in operator=(const wchar_t * p) const {return p;}
+
+ api::file_in operator<(const boost::filesystem::path &p) const {return p;}
+ api::file_in operator<(const std::string &p) const {return p;}
+ api::file_in operator<(const std::wstring &p) const {return p;}
+ api::file_in operator<(const char*p) const {return p;}
+ api::file_in operator<(const wchar_t * p) const {return p;}
+
+ api::file_in operator=(FILE * f) const {return f;}
+ api::file_in operator<(FILE * f) const {return f;}
+
+ template<typename Char, typename Traits> api::pipe_in operator=(basic_pipe<Char, Traits> & p) const {return p;}
+ template<typename Char, typename Traits> api::pipe_in operator<(basic_pipe<Char, Traits> & p) const {return p;}
+ template<typename Char, typename Traits> api::pipe_in operator=(basic_opstream<Char, Traits> & p) const {return p.pipe();}
+ template<typename Char, typename Traits> api::pipe_in operator<(basic_opstream<Char, Traits> & p) const {return p.pipe();}
+ template<typename Char, typename Traits> api::pipe_in operator=(basic_pstream <Char, Traits> & p) const {return p.pipe();}
+ template<typename Char, typename Traits> api::pipe_in operator<(basic_pstream <Char, Traits> & p) const {return p.pipe();}
+
+ api::async_pipe_in operator=(async_pipe & p) const {return p;}
+ api::async_pipe_in operator<(async_pipe & p) const {return p;}
+
+ template<typename T, typename = typename std::enable_if<
+ is_const_buffer<T>::value || is_mutable_buffer<T>::value
+ >::type>
+ api::async_in_buffer<const T> operator=(const T & buf) const {return buf;}
+ template<typename T, typename = typename std::enable_if<is_streambuf<T>::value>::type >
+ api::async_in_buffer<T> operator=(T & buf) const {return buf;}
+
+ template<typename T, typename = typename std::enable_if<
+ is_const_buffer<T>::value || is_mutable_buffer<T>::value
+ >::type>
+ api::async_in_buffer<const T> operator<(const T & buf) const {return buf;}
+ template<typename T, typename = typename std::enable_if<is_streambuf<T>::value>::type >
+ api::async_in_buffer<T> operator<(T & buf) const {return buf;}
+
+};
+
+//-1 == empty.
+//1 == stdout
+//2 == stderr
+template<int p1, int p2 = -1>
+struct std_out_
+{
+ constexpr std_out_() {}
+
+ api::close_out<p1,p2> close() const {return api::close_out<p1,p2>(); }
+ api::close_out<p1,p2> operator=(const close_t &) const {return api::close_out<p1,p2>();}
+ api::close_out<p1,p2> operator>(const close_t &) const {return api::close_out<p1,p2>();}
+
+ api::null_out<p1,p2> null() const {return api::null_out<p1,p2>();}
+ api::null_out<p1,p2> operator=(const null_t &) const {return api::null_out<p1,p2>();}
+ api::null_out<p1,p2> operator>(const null_t &) const {return api::null_out<p1,p2>();}
+
+ api::file_out<p1,p2> operator=(const boost::filesystem::path &p) const {return api::file_out<p1,p2>(p);}
+ api::file_out<p1,p2> operator=(const std::string &p) const {return api::file_out<p1,p2>(p);}
+ api::file_out<p1,p2> operator=(const std::wstring &p) const {return api::file_out<p1,p2>(p);}
+ api::file_out<p1,p2> operator=(const char * p) const {return api::file_out<p1,p2>(p);}
+ api::file_out<p1,p2> operator=(const wchar_t * p) const {return api::file_out<p1,p2>(p);}
+
+ api::file_out<p1,p2> operator>(const boost::filesystem::path &p) const {return api::file_out<p1,p2>(p);}
+ api::file_out<p1,p2> operator>(const std::string &p) const {return api::file_out<p1,p2>(p);}
+ api::file_out<p1,p2> operator>(const std::wstring &p) const {return api::file_out<p1,p2>(p);}
+ api::file_out<p1,p2> operator>(const char * p) const {return api::file_out<p1,p2>(p);}
+ api::file_out<p1,p2> operator>(const wchar_t * p) const {return api::file_out<p1,p2>(p);}
+
+ api::file_out<p1,p2> operator=(FILE * f) const {return f;}
+ api::file_out<p1,p2> operator>(FILE * f) const {return f;}
+
+ template<typename Char, typename Traits> api::pipe_out<p1,p2> operator=(basic_pipe<Char, Traits> & p) const {return p;}
+ template<typename Char, typename Traits> api::pipe_out<p1,p2> operator>(basic_pipe<Char, Traits> & p) const {return p;}
+ template<typename Char, typename Traits> api::pipe_out<p1,p2> operator=(basic_ipstream<Char, Traits> & p) const {return p.pipe();}
+ template<typename Char, typename Traits> api::pipe_out<p1,p2> operator>(basic_ipstream<Char, Traits> & p) const {return p.pipe();}
+ template<typename Char, typename Traits> api::pipe_out<p1,p2> operator=(basic_pstream <Char, Traits> & p) const {return p.pipe();}
+ template<typename Char, typename Traits> api::pipe_out<p1,p2> operator>(basic_pstream <Char, Traits> & p) const {return p.pipe();}
+
+ api::async_pipe_out<p1, p2> operator=(async_pipe & p) const {return p;}
+ api::async_pipe_out<p1, p2> operator>(async_pipe & p) const {return p;}
+
+ api::async_out_buffer<p1, p2, const asio::mutable_buffer> operator=(const asio::mutable_buffer & buf) const {return buf;}
+ api::async_out_buffer<p1, p2, const asio::mutable_buffers_1> operator=(const asio::mutable_buffers_1 & buf) const {return buf;}
+ api::async_out_buffer<p1, p2, asio::streambuf> operator=(asio::streambuf & os) const {return os ;}
+
+ api::async_out_buffer<p1, p2, const asio::mutable_buffer> operator>(const asio::mutable_buffer & buf) const {return buf;}
+ api::async_out_buffer<p1, p2, const asio::mutable_buffers_1> operator>(const asio::mutable_buffers_1 & buf) const {return buf;}
+ api::async_out_buffer<p1, p2, asio::streambuf> operator>(asio::streambuf & os) const {return os ;}
+
+ api::async_out_future<p1,p2, std::string> operator=(std::future<std::string> & fut) const { return fut;}
+ api::async_out_future<p1,p2, std::string> operator>(std::future<std::string> & fut) const { return fut;}
+ api::async_out_future<p1,p2, std::vector<char>> operator=(std::future<std::vector<char>> & fut) const { return fut;}
+ api::async_out_future<p1,p2, std::vector<char>> operator>(std::future<std::vector<char>> & fut) const { return fut;}
+
+ template<int pin, typename = typename std::enable_if<
+ (((p1 == 1) && (pin == 2)) ||
+ ((p1 == 2) && (pin == 1)))
+ && (p2 == -1)>::type>
+ constexpr std_out_<1, 2> operator& (const std_out_<pin>&) const
+ {
+ return std_out_<1, 2> ();
+ }
+
+};
+
+struct close_t
+{
+ constexpr close_t() {}
+ template<int T, int U>
+ api::close_out<T,U> operator()(std_out_<T,U>) {return api::close_out<T,U>();}
+};
+
+
+
+}
+///This constant is a utility to allow syntax like `std_out > close` for closing I/O streams.
+constexpr boost::process::detail::close_t close;
+///This constant is a utility to redirect streams to the null-device.
+constexpr boost::process::detail::null_t null;
+
+/**
+This property allows to set the input stream for the child process.
+
+\section stdin_details Details
+
+\subsection stdin_file File Input
+
+The file I/O simple redirects the stream to a file, for which the possible types are
+
+ - `boost::filesystem::path`
+ - `std::basic_string<char_type>`
+ - `const char_type*`
+ - `FILE*`
+
+with `char_type` being either `char` or `wchar_t`.
+
+FILE* is explicitly added, so the process can easily redirect the output stream
+of the child to another output stream of the process. That is:
+
+\code{.cpp}
+system("ls", std_in < stdin);
+\endcode
+
+\warning If the launching and the child process use the input, this leads to undefined behaviour.
+
+A syntax like `system("ls", std_out > std::cerr)` is not possible, due to the C++
+implementation not providing access to the handle.
+
+The valid expressions for this property are
+
+\code{.cpp}
+std_in < file;
+std_in = file;
+\endcode
+
+\subsection stdin_pipe Pipe Input
+
+As explained in the corresponding section, the boost.process library provides a
+@ref boost::process::async_pipe "async_pipe" class which can be
+used to communicate with child processes.
+
+\note Technically the @ref boost::process::async_pipe "async_pipe"
+works synchronous here, since no asio implementation is used by the library here.
+The async-operation will then however not end if the process is finished, since
+the pipe remains open. You can use the async_close function with on_exit to fix that.
+
+Valid expressions with pipes are these:
+
+\code{.cpp}
+std_in < pipe;
+std_in = pipe;
+\endcode
+
+Where the valid types for `pipe` are the following:
+
+ - `basic_pipe`
+ - `async_pipe`
+ - `basic_opstream`
+ - `basic_pstream`
+
+Note that the pipe may also be used between several processes, like this:
+
+\code{.cpp}
+pipe p;
+child c1("nm", "a.out", std_out>p);
+child c2("c++filt", std_in<p);
+\endcode
+
+\subsection stdin_async_pipe Asynchronous Pipe Input
+
+Asynchronous Pipe I/O classifies communication which has automatically handling
+of the asynchronous operations by the process library. This means, that a pipe will be
+constructed, the async_read/-write will be automatically started, and that the
+end of the child process will also close the pipe.
+
+Valid types for pipe I/O are the following:
+
+ - `boost::asio::const_buffer` \xmlonly <footnote><para> Constructed with <code>boost::asio::buffer</code></para></footnote> \endxmlonly
+ - `boost::asio::mutable_buffer` \xmlonly <footnote><para> Constructed with <code>boost::asio::buffer</code></para></footnote> \endxmlonly
+ - `boost::asio::streambuf`
+
+Valid expressions with pipes are these:
+
+\code{.cpp}
+std_in < buffer;
+std_in = buffer;
+std_out > buffer;
+std_out = buffer;
+std_err > buffer;
+std_err = buffer;
+(std_out & std_err) > buffer;
+(std_out & std_err) = buffer;
+\endcode
+
+\note It is also possible to get a future for std_in, by chaining another `std::future<void>` onto it,
+so you can wait for the input to be completed. It looks like this:
+\code{.cpp}
+std::future<void> fut;
+boost::asio::io_service ios;
+std::string data;
+child c("prog", std_in < buffer(data) > fut, ios);
+fut.get();
+\endcode
+
+
+\note `boost::asio::buffer` is also available in the `boost::process` namespace.
+
+\warning This feature requires `boost/process/async.hpp` to be included and a reference to `boost::asio::io_service` to be passed to the launching function.
+
+
+\subsection stdin_close Close
+
+The input stream can be closed, so it cannot be read from. This will lead to an error when attempted.
+
+This can be achieved by the following syntax.
+
+\code{.cpp}
+std_in < close;
+std_in = close;
+std_in.close();
+\endcode
+
+\subsection stdin_null Null
+
+The input stream can be redirected to read from the null-device, which means that only `EOF` is read.
+
+The syntax to achieve that has the following variants:
+
+\code{.cpp}
+std_in < null;
+std_in = null;
+std_in.null();
+\endcode
+
+*/
+
+constexpr boost::process::detail::std_in_<void> std_in;
+
+/**
+This property allows to set the output stream for the child process.
+
+\note The Semantic is the same as for \xmlonly <globalname alt="boost::process::std_err">std_err</globalname> \endxmlonly
+
+\note `std_err` and `std_out` can be combined into one stream, with the `operator &`, i.e. `std_out & std_err`.
+
+\section stdout_details Details
+
+\subsection stdout_file File Input
+
+The file I/O simple redirects the stream to a file, for which the possible types are
+
+ - `boost::filesystem::path`
+ - `std::basic_string<char_type>`
+ - `const char_type*`
+ - `FILE*`
+
+with `char_type` being either `char` or `wchar_t`.
+
+FILE* is explicitly added, so the process can easily redirect the output stream
+of the child to another output stream of the process. That is:
+
+\code{.cpp}
+system("ls", std_out < stdin);
+\endcode
+
+\warning If the launching and the child process use the input, this leads to undefined behaviour.
+
+A syntax like `system("ls", std_out > std::cerr)` is not possible, due to the C++
+implementation not providing access to the handle.
+
+The valid expressions for this property are
+
+\code{.cpp}
+std_out < file;
+std_out = file;
+\endcode
+
+\subsection stdout_pipe Pipe Output
+
+As explained in the corresponding section, the boost.process library provides a
+@ref boost::process::async_pipe "async_pipe" class which can be
+used to communicate with child processes.
+
+\note Technically the @ref boost::process::async_pipe "async_pipe"
+works like a synchronous pipe here, since no asio implementation is used by the library here.
+The asynchronous operation will then however not end if the process is finished, since
+the pipe remains open. You can use the async_close function with on_exit to fix that.
+
+Valid expressions with pipes are these:
+
+\code{.cpp}
+std_out > pipe;
+std_out = pipe;
+\endcode
+
+Where the valid types for `pipe` are the following:
+
+ - `basic_pipe`
+ - `async_pipe`
+ - `basic_ipstream`
+ - `basic_pstream`
+
+Note that the pipe may also be used between several processes, like this:
+
+\code{.cpp}
+pipe p;
+child c1("nm", "a.out", std_out>p);
+child c2("c++filt", std_in<p);
+\endcode
+
+\subsection stdout_async_pipe Asynchronous Pipe Output
+
+Asynchronous Pipe I/O classifies communication which has automatically handling
+of the async operations by the process library. This means, that a pipe will be
+constructed, the async_read/-write will be automatically started, and that the
+end of the child process will also close the pipe.
+
+Valid types for pipe I/O are the following:
+
+ - `boost::asio::mutable_buffer` \xmlonly <footnote><para> Constructed with <code>boost::asio::buffer</code></para></footnote> \endxmlonly
+ - `boost::asio::streambuf`
+ - `std::future<std::vector<char>>`
+ - `std::future<std::string>`
+
+Valid expressions with pipes are these:
+
+\code{.cpp}
+std_out > buffer;
+std_out = buffer;
+std_err > buffer;
+std_err = buffer;
+(std_out & std_err) > buffer;
+(std_out & std_err) = buffer;
+\endcode
+
+\note `boost::asio::buffer` is also available in the `boost::process` namespace.
+
+\warning This feature requires `boost/process/async.hpp` to be included and a reference to `boost::asio::io_service` to be passed to the launching function.
+
+
+\subsection stdout_close Close
+
+The out stream can be closed, so it cannot be write from.
+This will lead to an error when attempted.
+
+This can be achieved by the following syntax.
+
+\code{.cpp}
+std_out > close;
+std_out = close;
+std_out.close();
+\endcode
+
+\subsection stdout_null Null
+
+The output stream can be redirected to write to the null-device,
+which means that all output is discarded.
+
+The syntax to achieve that has the following variants:
+
+\code{.cpp}
+std_out > null;
+std_out = null;
+std_out.null();
+\endcode
+
+*/
+
+constexpr boost::process::detail::std_out_<1> std_out;
+/**This property allows setting the `stderr` stream. The semantic and syntax is the same as for
+ * \xmlonly <globalname alt="boost::process::std_out">std_out</globalname> \endxmlonly .
+ */
+constexpr boost::process::detail::std_out_<2> std_err;
+
+}}
+#endif /* INCLUDE_BOOST_PROCESS_IO_HPP_ */
diff --git a/boost/process/locale.hpp b/boost/process/locale.hpp
new file mode 100644
index 0000000000..c8bcf4f9ea
--- /dev/null
+++ b/boost/process/locale.hpp
@@ -0,0 +1,246 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+// Copyright (c) 2008 Beman Dawes
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_LOCALE_HPP_
+#define BOOST_PROCESS_LOCALE_HPP_
+
+#include <system_error>
+#include <boost/process/detail/config.hpp>
+
+#if defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/locale.hpp>
+# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
+|| defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
+#include <codecvt>
+#endif
+
+#include <locale>
+
+namespace boost
+{
+namespace process
+{
+namespace detail
+{
+
+class codecvt_category_t : public std::error_category
+{
+public:
+ codecvt_category_t(){}
+ const char* name() const noexcept override {return "codecvt";}
+ std::string message(int ev) const override
+ {
+ std::string str;
+ switch (ev)
+ {
+ case std::codecvt_base::ok:
+ str = "ok";
+ break;
+ case std::codecvt_base::partial:
+ str = "partial";
+ break;
+ case std::codecvt_base::error:
+ str = "error";
+ break;
+ case std::codecvt_base::noconv:
+ str = "noconv";
+ break;
+ default:
+ str = "unknown error";
+ }
+ return str;
+ }
+};
+
+}
+
+///Internally used error cateory for code conversion.
+inline const std::error_category& codecvt_category()
+{
+ static const ::boost::process::detail::codecvt_category_t cat;
+ return cat;
+}
+
+namespace detail
+{
+//copied from boost.filesystem
+inline std::locale default_locale()
+{
+# if defined(BOOST_WINDOWS_API)
+ std::locale global_loc = std::locale();
+ return std::locale(global_loc, new boost::process::detail::windows::windows_file_codecvt);
+# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
+|| defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
+ std::locale global_loc = std::locale();
+ return std::locale(global_loc, new std::codecvt_utf8<wchar_t>);
+# else // Other POSIX
+ // ISO C calls std::locale("") "the locale-specific native environment", and this
+ // locale is the default for many POSIX-based operating systems such as Linux.
+ return std::locale("");
+# endif
+}
+
+inline std::locale& process_locale()
+{
+ static std::locale loc(default_locale());
+ return loc;
+}
+
+}
+
+///The internally used type for code conversion.
+typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_type;
+
+///Get a reference to the currently used code converter.
+inline const codecvt_type& codecvt()
+{
+ return std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(
+ detail::process_locale());
+}
+
+///Set the locale of the library.
+inline std::locale imbue(const std::locale& loc)
+{
+ std::locale temp(detail::process_locale());
+ detail::process_locale() = loc;
+ return temp;
+}
+
+
+namespace detail
+{
+
+inline std::size_t convert(const char* from,
+ const char* from_end,
+ wchar_t* to, wchar_t* to_end,
+ const ::boost::process::codecvt_type & cvt =
+ ::boost::process::codecvt())
+{
+ std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports
+ const char* from_next;
+ wchar_t* to_next;
+
+ auto res = cvt.in(state, from, from_end, from_next,
+ to, to_end, to_next);
+
+ if (res != std::codecvt_base::ok)
+ throw process_error(res, ::boost::process::codecvt_category(),
+ "boost::process codecvt to wchar_t");
+
+
+ return to_next - to;
+
+}
+
+inline std::size_t convert(const wchar_t* from,
+ const wchar_t* from_end,
+ char* to, char* to_end,
+ const ::boost::process::codecvt_type & cvt =
+ ::boost::process::codecvt())
+{
+ std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports
+ const wchar_t* from_next;
+ char* to_next;
+
+ std::codecvt_base::result res;
+
+ if ((res=cvt.out(state, from, from_end, from_next,
+ to, to_end, to_next)) != std::codecvt_base::ok)
+ throw process_error(res, ::boost::process::codecvt_category(),
+ "boost::process codecvt to char");
+
+ return to_next - to;
+}
+
+inline std::wstring convert(const std::string & st,
+ const ::boost::process::codecvt_type & cvt =
+ ::boost::process::codecvt())
+{
+ std::wstring out(st.size() + 10, ' '); //just to be sure
+ auto sz = convert(st.c_str(), st.c_str() + st.size(),
+ &out.front(), &out.back(), cvt);
+
+ out.resize(sz);
+ return out;
+}
+
+inline std::string convert(const std::wstring & st,
+ const ::boost::process::codecvt_type & cvt =
+ ::boost::process::codecvt())
+{
+ std::string out(st.size() * 2, ' '); //just to be sure
+ auto sz = convert(st.c_str(), st.c_str() + st.size(),
+ &out.front(), &out.back(), cvt);
+
+ out.resize(sz);
+ return out;
+}
+
+inline std::vector<wchar_t> convert(const std::vector<char> & st,
+ const ::boost::process::codecvt_type & cvt =
+ ::boost::process::codecvt())
+{
+ std::vector<wchar_t> out(st.size() + 10); //just to be sure
+ auto sz = convert(st.data(), st.data() + st.size(),
+ &out.front(), &out.back(), cvt);
+
+ out.resize(sz);
+ return out;
+}
+
+inline std::vector<char> convert(const std::vector<wchar_t> & st,
+ const ::boost::process::codecvt_type & cvt =
+ ::boost::process::codecvt())
+{
+ std::vector<char> out(st.size() * 2); //just to be sure
+ auto sz = convert(st.data(), st.data() + st.size(),
+ &out.front(), &out.back(), cvt);
+
+ out.resize(sz);
+ return out;
+}
+
+
+inline std::wstring convert(const char *begin, const char* end,
+ const ::boost::process::codecvt_type & cvt =
+ ::boost::process::codecvt())
+{
+ auto size = end-begin;
+ std::wstring out(size + 10, ' '); //just to be sure
+ using namespace std;
+ auto sz = convert(begin, end,
+ &out.front(), &out.back(), cvt);
+ out.resize(sz);
+ return out;
+}
+
+inline std::string convert(const wchar_t * begin, const wchar_t *end,
+ const ::boost::process::codecvt_type & cvt =
+ ::boost::process::codecvt())
+{
+ auto size = end-begin;
+
+ std::string out(size * 2, ' '); //just to be sure
+ auto sz = convert(begin, end ,
+ &out.front(), &out.back(), cvt);
+
+ out.resize(sz);
+ return out;
+}
+
+
+
+
+}
+
+
+
+}
+}
+
+
+
+
+#endif /* BOOST_PROCESS_LOCALE_HPP_ */
diff --git a/boost/process/pipe.hpp b/boost/process/pipe.hpp
new file mode 100644
index 0000000000..8af776f966
--- /dev/null
+++ b/boost/process/pipe.hpp
@@ -0,0 +1,475 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_PIPE_HPP
+#define BOOST_PROCESS_PIPE_HPP
+
+#include <boost/config.hpp>
+#include <boost/process/detail/config.hpp>
+#include <streambuf>
+#include <istream>
+#include <ostream>
+#include <vector>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/basic_pipe.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/basic_pipe.hpp>
+#endif
+
+namespace boost { namespace process {
+
+using ::boost::process::detail::api::basic_pipe;
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+/** Class implementation of a pipe.
+ *
+ */
+template<class CharT, class Traits = std::char_traits<CharT>>
+class basic_pipe
+{
+public:
+ typedef CharT char_type ;
+ typedef Traits traits_type;
+ typedef typename Traits::int_type int_type ;
+ typedef typename Traits::pos_type pos_type ;
+ typedef typename Traits::off_type off_type ;
+ typedef ::boost::detail::winapi::HANDLE_ native_handle;
+
+ /// Default construct the pipe. Will be opened.
+ basic_pipe();
+
+ ///Construct a named pipe.
+ inline explicit basic_pipe(const std::string & name);
+ /** Copy construct the pipe.
+ * \note Duplicated the handles.
+ */
+ inline basic_pipe(const basic_pipe& p);
+ /** Move construct the pipe. */
+ basic_pipe(basic_pipe&& lhs);
+ /** Copy assign the pipe.
+ * \note Duplicated the handles.
+ */
+ inline basic_pipe& operator=(const basic_pipe& p);
+ /** Move assign the pipe. */
+ basic_pipe& operator=(basic_pipe&& lhs);
+ /** Destructor closes the handles. */
+ ~basic_pipe();
+ /** Get the native handle of the source. */
+ native_handle native_source() const;
+ /** Get the native handle of the sink. */
+ native_handle native_sink () const;
+
+ /** Assign a new value to the source */
+ void assign_source(native_handle h);
+ /** Assign a new value to the sink */
+ void assign_sink (native_handle h);
+
+
+ ///Write data to the pipe.
+ int_type write(const char_type * data, int_type count);
+ ///Read data from the pipe.
+ int_type read(char_type * data, int_type count);
+ ///Check if the pipe is open.
+ bool is_open();
+ ///Close the pipe
+ void close();
+};
+
+#endif
+
+
+
+typedef basic_pipe<char> pipe;
+typedef basic_pipe<wchar_t> wpipe;
+
+
+/** Implementation of the stream buffer for a pipe.
+ */
+template<
+ class CharT,
+ class Traits = std::char_traits<CharT>
+>
+struct basic_pipebuf : std::basic_streambuf<CharT, Traits>
+{
+ typedef basic_pipe<CharT, Traits> pipe_type;
+
+ typedef CharT char_type ;
+ typedef Traits traits_type;
+ typedef typename Traits::int_type int_type ;
+ typedef typename Traits::pos_type pos_type ;
+ typedef typename Traits::off_type off_type ;
+
+ constexpr static int default_buffer_size = BOOST_PROCESS_PIPE_SIZE;
+
+ ///Default constructor, will also construct the pipe.
+ basic_pipebuf() : _write(default_buffer_size), _read(default_buffer_size)
+ {
+ this->setg(_read.data(), _read.data()+ 128, _read.data() + 128);
+ this->setp(_write.data(), _write.data() + _write.size());
+ }
+ ///Copy Constructor.
+ basic_pipebuf(const basic_pipebuf & ) = default;
+ ///Move Constructor
+ basic_pipebuf(basic_pipebuf && ) = default;
+
+ ///Move construct from a pipe.
+ basic_pipebuf(pipe_type && p) : _pipe(std::move(p)),
+ _write(default_buffer_size),
+ _read(default_buffer_size)
+ {
+ this->setg(_read.data(), _read.data()+ 128, _read.data() + 128);
+ this->setp(_write.data(), _write.data() + _write.size());
+ }
+ ///Construct from a pipe.
+ basic_pipebuf(const pipe_type & p) : _pipe(p),
+ _write(default_buffer_size),
+ _read(default_buffer_size)
+ {
+ this->setg(_read.data(), _read.data()+ 128, _read.data() + 128);
+ this->setp(_write.data(), _write.data() + _write.size());
+ }
+ ///Copy assign.
+ basic_pipebuf& operator=(const basic_pipebuf & ) = delete;
+ ///Move assign.
+ basic_pipebuf& operator=(basic_pipebuf && ) = default;
+ ///Move assign a pipe.
+ basic_pipebuf& operator=(pipe_type && p)
+ {
+ _pipe = std::move(p);
+ return *this;
+ }
+ ///Copy assign a pipe.
+ basic_pipebuf& operator=(const pipe_type & p)
+ {
+ _pipe = p;
+ return *this;
+ }
+ ///Writes characters to the associated output sequence from the put area
+ int_type overflow(int_type ch = traits_type::eof()) override
+ {
+ if ((ch != traits_type::eof()) && _pipe.is_open())
+ {
+ if (this->pptr() == this->epptr())
+ {
+ bool wr = this->_write_impl();
+ *this->pptr() = ch;
+ this->pbump(1);
+ if (wr)
+ return ch;
+ }
+ else
+ {
+ *this->pptr() = ch;
+ this->pbump(1);
+ if (this->_write_impl())
+ return ch;
+ }
+ }
+ return traits_type::eof();
+ }
+ ///Synchronizes the buffers with the associated character sequence
+ int sync() override { return this->_write_impl() ? 0 : -1; }
+
+ ///Reads characters from the associated input sequence to the get area
+ int_type underflow() override
+ {
+ if (!_pipe.is_open())
+ return traits_type::eof();
+
+ if (this->egptr() == &_read.back()) //ok, so we're at the end of the buffer
+ this->setg(_read.data(), _read.data()+ 10, _read.data() + 10);
+
+
+ auto len = &_read.back() - this->egptr() ;
+ auto res = _pipe.read(
+ this->egptr(),
+ static_cast<typename pipe_type::int_type>(len));
+ if (res == 0)
+ return traits_type::eof();
+
+ this->setg(this->eback(), this->gptr(), this->egptr() + res);
+ auto val = *this->gptr();
+
+ return traits_type::to_int_type(val);
+ }
+
+
+ ///Set the pipe of the streambuf.
+ void pipe(pipe_type&& p) {_pipe = std::move(p); }
+ ///Set the pipe of the streambuf.
+ void pipe(const pipe_type& p) {_pipe = p; }
+ ///Get a reference to the pipe.
+ pipe_type & pipe() & {return _pipe;}
+ ///Get a const reference to the pipe.
+ const pipe_type &pipe() const & {return _pipe;}
+ ///Get a rvalue reference to the pipe. Qualified as rvalue.
+ pipe_type && pipe() && {return std::move(_pipe);}
+private:
+ pipe_type _pipe;
+ std::vector<char_type> _write;
+ std::vector<char_type> _read;
+
+ bool _write_impl()
+ {
+ if (!_pipe.is_open())
+ return false;
+
+ auto base = this->pbase();
+ auto wrt = _pipe.write(base,
+ static_cast<typename pipe_type::int_type>(this->pptr() - base));
+ std::ptrdiff_t diff = this->pptr() - base;
+
+ if (wrt < diff)
+ std::move(base + wrt, base + diff, base);
+ else if (wrt == 0) //broken pipe
+ return false;
+
+ this->pbump(-wrt);
+
+ return true;
+ }
+};
+
+typedef basic_pipebuf<char> pipebuf;
+typedef basic_pipebuf<wchar_t> wpipebuf;
+
+/** Implementation of a reading pipe stream.
+ *
+ */
+template<
+ class CharT,
+ class Traits = std::char_traits<CharT>
+>
+class basic_ipstream : public std::basic_istream<CharT, Traits>
+{
+ basic_pipebuf<CharT, Traits> _buf;
+public:
+
+ typedef basic_pipe<CharT, Traits> pipe_type;
+
+ typedef CharT char_type ;
+ typedef Traits traits_type;
+ typedef typename Traits::int_type int_type ;
+ typedef typename Traits::pos_type pos_type ;
+ typedef typename Traits::off_type off_type ;
+
+ ///Get access to the underlying stream_buf
+ basic_pipebuf<CharT, Traits>* rdbuf() const {return _buf;};
+
+ ///Default constructor.
+ basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr)
+ {
+ std::basic_istream<CharT, Traits>::rdbuf(&_buf);
+ };
+ ///Copy constructor.
+ basic_ipstream(const basic_ipstream & ) = delete;
+ ///Move constructor.
+ basic_ipstream(basic_ipstream && ) = default;
+
+ ///Move construct from a pipe.
+ basic_ipstream(pipe_type && p) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(p))
+ {
+ std::basic_istream<CharT, Traits>::rdbuf(&_buf);
+ }
+
+ ///Copy construct from a pipe.
+ basic_ipstream(const pipe_type & p) : std::basic_istream<CharT, Traits>(nullptr), _buf(p)
+ {
+ std::basic_istream<CharT, Traits>::rdbuf(&_buf);
+ }
+
+ ///Copy assignment.
+ basic_ipstream& operator=(const basic_ipstream & ) = delete;
+ ///Move assignment
+ basic_ipstream& operator=(basic_ipstream && ) = default;
+ ///Move assignment of a pipe.
+ basic_ipstream& operator=(pipe_type && p)
+ {
+ _buf = std::move(p);
+ return *this;
+ }
+ ///Copy assignment of a pipe.
+ basic_ipstream& operator=(const pipe_type & p)
+ {
+ _buf = p;
+ return *this;
+ }
+ ///Set the pipe of the streambuf.
+ void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); }
+ ///Set the pipe of the streambuf.
+ void pipe(const pipe_type& p) {_buf.pipe(p); }
+ ///Get a reference to the pipe.
+ pipe_type & pipe() & {return _buf.pipe();}
+ ///Get a const reference to the pipe.
+ const pipe_type &pipe() const & {return _buf.pipe();}
+ ///Get a rvalue reference to the pipe. Qualified as rvalue.
+ pipe_type && pipe() && {return std::move(_buf).pipe();}
+};
+
+typedef basic_ipstream<char> ipstream;
+typedef basic_ipstream<wchar_t> wipstream;
+
+/** Implementation of a write pipe stream.
+ *
+ */
+template<
+ class CharT,
+ class Traits = std::char_traits<CharT>
+>
+class basic_opstream : public std::basic_ostream<CharT, Traits>
+{
+ basic_pipebuf<CharT, Traits> _buf;
+public:
+ typedef basic_pipe<CharT, Traits> pipe_type;
+
+ typedef CharT char_type ;
+ typedef Traits traits_type;
+ typedef typename Traits::int_type int_type ;
+ typedef typename Traits::pos_type pos_type ;
+ typedef typename Traits::off_type off_type ;
+
+
+ ///Get access to the underlying stream_buf
+ basic_pipebuf<CharT, Traits>* rdbuf() const {return _buf;};
+
+ ///Default constructor.
+ basic_opstream() : std::basic_ostream<CharT, Traits>(nullptr)
+ {
+ std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
+ };
+ ///Copy constructor.
+ basic_opstream(const basic_opstream & ) = delete;
+ ///Move constructor.
+ basic_opstream(basic_opstream && ) = default;
+
+ ///Move construct from a pipe.
+ basic_opstream(pipe_type && p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(p))
+ {
+ std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
+ };
+ ///Copy construct from a pipe.
+ basic_opstream(const pipe_type & p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(p)
+ {
+ std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
+ };
+ ///Copy assignment.
+ basic_opstream& operator=(const basic_opstream & ) = delete;
+ ///Move assignment
+ basic_opstream& operator=(basic_opstream && ) = default;
+ ///Move assignment of a pipe.
+ basic_opstream& operator=(pipe_type && p)
+ {
+ _buf = std::move(p);
+ return *this;
+ }
+ ///Copy assignment of a pipe.
+ basic_opstream& operator=(const pipe_type & p)
+ {
+ _buf = p;
+ return *this;
+ }
+ ///Set the pipe of the streambuf.
+ void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); }
+ ///Set the pipe of the streambuf.
+ void pipe(const pipe_type& p) {_buf.pipe(p); }
+ ///Get a reference to the pipe.
+ pipe_type & pipe() & {return _buf.pipe();}
+ ///Get a const reference to the pipe.
+ const pipe_type &pipe() const & {return _buf.pipe();}
+ ///Get a rvalue reference to the pipe. Qualified as rvalue.
+ pipe_type && pipe() && {return std::move(_buf).pipe();}
+};
+
+typedef basic_opstream<char> opstream;
+typedef basic_opstream<wchar_t> wopstream;
+
+
+/** Implementation of a read-write pipe stream.
+ *
+ */
+template<
+ class CharT,
+ class Traits = std::char_traits<CharT>
+>
+class basic_pstream : public std::basic_iostream<CharT, Traits>
+{
+ basic_pipebuf<CharT, Traits> _buf;
+public:
+ typedef basic_pipe<CharT, Traits> pipe_type;
+
+ typedef CharT char_type ;
+ typedef Traits traits_type;
+ typedef typename Traits::int_type int_type ;
+ typedef typename Traits::pos_type pos_type ;
+ typedef typename Traits::off_type off_type ;
+
+
+ ///Get access to the underlying stream_buf
+ basic_pipebuf<CharT, Traits>* rdbuf() const {return _buf;};
+
+ ///Default constructor.
+ basic_pstream() : std::basic_iostream<CharT, Traits>(nullptr)
+ {
+ std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
+ };
+ ///Copy constructor.
+ basic_pstream(const basic_pstream & ) = delete;
+ ///Move constructor.
+ basic_pstream(basic_pstream && ) = default;
+
+ ///Move construct from a pipe.
+ basic_pstream(pipe_type && p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(p))
+ {
+ std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
+ };
+ ///Copy construct from a pipe.
+ basic_pstream(const pipe_type & p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(p)
+ {
+ std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
+ };
+ ///Copy assignment.
+ basic_pstream& operator=(const basic_pstream & ) = delete;
+ ///Move assignment
+ basic_pstream& operator=(basic_pstream && ) = default;
+ ///Move assignment of a pipe.
+ basic_pstream& operator=(pipe_type && p)
+ {
+ _buf = std::move(p);
+ return *this;
+ }
+ ///Copy assignment of a pipe.
+ basic_pstream& operator=(const pipe_type & p)
+ {
+ _buf = p;
+ return *this;
+ }
+ ///Set the pipe of the streambuf.
+ void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); }
+ ///Set the pipe of the streambuf.
+ void pipe(const pipe_type& p) {_buf.pipe(p); }
+ ///Get a reference to the pipe.
+ pipe_type & pipe() & {return _buf.pipe();}
+ ///Get a const reference to the pipe.
+ const pipe_type &pipe() const & {return _buf.pipe();}
+ ///Get a rvalue reference to the pipe. Qualified as rvalue.
+ pipe_type && pipe() && {return std::move(_buf).pipe();}
+};
+
+typedef basic_pstream<char> pstream;
+typedef basic_pstream<wchar_t> wpstream;
+
+
+
+}}
+
+
+
+#endif
diff --git a/boost/process/posix.hpp b/boost/process/posix.hpp
new file mode 100644
index 0000000000..909837b8aa
--- /dev/null
+++ b/boost/process/posix.hpp
@@ -0,0 +1,75 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_PROCESS_POSIX_HPP_
+#define BOOST_PROCESS_POSIX_HPP_
+
+#include <boost/process/detail/posix/fd.hpp>
+#include <boost/process/detail/posix/handler.hpp>
+#include <boost/process/detail/posix/use_vfork.hpp>
+#include <boost/process/detail/posix/signal.hpp>
+
+
+/** \file boost/process/posix.hpp
+ *
+ * Header which provides the posix extensions.
+\xmlonly
+<programlisting>
+namespace boost {
+ namespace process {
+ namespace posix {
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::posix::fd">fd</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::posix::sig">sig</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::posix::use_vfork">use_vfork</globalname>;
+ }
+ }
+}
+</programlisting>
+ * \endxmlonly
+ * \warning Only available on posix. See the documentation of [fork](http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html),
+ * [execve](http://pubs.opengroup.org/onlinepubs/009695399/functions/execve.html) and
+ * [vfork](http://pubs.opengroup.org/onlinepubs/009695399/functions/vfork.html).
+ *
+ */
+
+namespace boost { namespace process {
+
+///Namespace containing the posix exensions.
+namespace posix {
+
+/** This property lets you modify file-descriptors other than the standard ones (0,1,2).
+ *
+ * It provides the functions `bind`, which implements [dup2](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)
+ * and [close](http://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html).
+ *
+ * Close can also be called with a range of file-descriptors to be closed.
+ *
+ */
+constexpr ::boost::process::detail::posix::fd_ fd;
+
+/** This property lets you modify the handling of `SIGCHLD` for this call. It will be reset afterwards.
+
+It can be set to default, by the expression `sig.dfl()`, set to ignore with `sig.ign()` or
+assigned a custom handler. A custom handler must have the type `sighandler_t`and can be assigned with the following syntax:
+
+\code{.cpp}
+sig = handler;
+sig(handler);
+\endcode
+
+\warning @ref spawn will automatically use `sig.ign()`, which will override if you pass a custom handler.
+ */
+constexpr ::boost::process::detail::posix::sig_ sig;
+/** This property will replace the usage of [fork](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html) by [vfork](http://pubs.opengroup.org/onlinepubs/009695399/functions/vfork.html).
+ \note `vfork` is no longer an official part of the posix standard.
+
+ */
+constexpr ::boost::process::detail::posix::use_vfork_ use_vfork;
+
+
+using ::boost::process::detail::posix::sighandler_t;
+
+}}}
+
+#endif /* BOOST_PROCESS_POSIX_HPP_ */
diff --git a/boost/process/search_path.hpp b/boost/process/search_path.hpp
new file mode 100644
index 0000000000..1c38a61608
--- /dev/null
+++ b/boost/process/search_path.hpp
@@ -0,0 +1,54 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the 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 boost/process/search_path.hpp
+ *
+ * Defines a function to search for an executable in path.
+ */
+
+#ifndef BOOST_PROCESS_SEARCH_PATH_HPP
+#define BOOST_PROCESS_SEARCH_PATH_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/environment.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/search_path.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/search_path.hpp>
+#endif
+
+
+namespace boost { namespace process {
+
+/**
+ * Searches for an executable in path.
+ *
+ * filename must be a basename including the file extension.
+ * It must not include any directory separators (like a slash).
+ * On Windows the file extension may be omitted. The function
+ * will then try the various file extensions for executables on
+ * Windows to find filename.
+ *
+ * \param filename The base of the filename to find
+ *
+ * \param path the set of paths so search, defaults to "PATH" environment variable.
+ *
+ * \returns the absolute path to the executable filename or an
+ * empty string if filename isn't found
+ */
+inline boost::filesystem::path search_path(const boost::filesystem::path &filename,
+ const std::vector<boost::filesystem::path> path = ::boost::this_process::path())
+{
+ return ::boost::process::detail::api::search_path(filename, path);
+}
+}}
+
+#endif
diff --git a/boost/process/shell.hpp b/boost/process/shell.hpp
new file mode 100644
index 0000000000..64314a688d
--- /dev/null
+++ b/boost/process/shell.hpp
@@ -0,0 +1,92 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_SHELL_PATH_HPP
+#define BOOST_PROCESS_SHELL_PATH_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/traits/wchar_t.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/detail/posix/shell_path.hpp>
+#elif defined(BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/shell_path.hpp>
+#endif
+
+/** \file boost/process/shell.hpp
+ *
+ * Header which provides the shell property. This provides the
+ * property to launch a process through the system shell.
+ * It also allows the user to obtain the shell-path via shell().
+\xmlonly
+<programlisting>
+namespace boost {
+ namespace process {
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::shell">shell</globalname>;
+ }
+}
+</programlisting>
+\endxmlonly
+
+ */
+
+namespace boost { namespace process { namespace detail {
+
+
+struct shell_
+{
+ constexpr shell_() {}
+
+ boost::filesystem::path operator()() const
+ {
+ return boost::process::detail::api::shell_path();
+ }
+ boost::filesystem::path operator()(std::error_code & ec) const noexcept
+ {
+ return boost::process::detail::api::shell_path(ec);
+ }
+};
+
+template<>
+struct is_wchar_t<shell_> : is_wchar_t<boost::filesystem::path>
+{
+};
+
+}
+/**
+The shell property enables to launch a program through the shell of the system.
+
+\code{.cpp}
+system("gcc", shell);
+\endcode
+
+The shell argument goes without any expression. The operator() is overloaded, to
+obtain the path of the system shell.
+
+\code{.cpp}
+auto shell_cmd = shell();
+//avoid exceptions
+std::error_code ec;
+shell_cmd = shell(ec);
+\endcode
+
+\attention Launching through the shell will NOT provide proper error handling, i.e.
+you will get an error via the return code.
+
+\attention Executing shell commands that incorporate unsanitized input from an untrusted source makes a program vulnerable to shell injection, a serious security flaw which can result in arbitrary command execution. For this reason, the use of `shell` is strongly discouraged in cases where the command string is constructed from external input:
+
+*/
+constexpr ::boost::process::detail::shell_ shell;
+
+}}
+
+
+
+#endif
diff --git a/boost/process/spawn.hpp b/boost/process/spawn.hpp
new file mode 100644
index 0000000000..fb1e3594b1
--- /dev/null
+++ b/boost/process/spawn.hpp
@@ -0,0 +1,69 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the 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 boost/process/spawn.hpp
+ *
+ * Defines the spawn function.
+ */
+
+#ifndef BOOST_PROCESS_SPAWN_HPP
+#define BOOST_PROCESS_SPAWN_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/child_decl.hpp>
+#include <boost/process/detail/execute_impl.hpp>
+#include <boost/process/detail/async_handler.hpp>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/posix.hpp>
+#endif
+
+namespace boost {
+
+namespace process {
+
+namespace detail {
+
+}
+
+/** Launch a process and detach it. Returns no handle.
+
+This function starts a process and immediately detaches it. It thereby prevents the system from creating a zombie process,
+but will also cause the system to be unable to wait for the child to exit.
+
+\note This will set `SIGCHLD` to `SIGIGN` on posix.
+
+\warning This function does not allow asynchronous operations, since it cannot wait for the end of the process.
+It will fail to compile if a reference to `boost::asio::io_service` is passed.
+
+ */
+template<typename ...Args>
+inline void spawn(Args && ...args)
+{
+ typedef typename ::boost::process::detail::has_async_handler<Args...>::type
+ has_async;
+
+
+ static_assert(
+ !has_async::value,
+ "Spawn cannot wait for exit, so async properties cannot be used");
+
+ auto c = ::boost::process::detail::execute_impl(
+#if defined(BOOST_POSIX_API)
+ ::boost::process::posix::sig.ign(),
+#endif
+ std::forward<Args>(args)...);
+ c.detach();
+}
+
+}}
+#endif
+
diff --git a/boost/process/start_dir.hpp b/boost/process/start_dir.hpp
new file mode 100644
index 0000000000..50a246f4b8
--- /dev/null
+++ b/boost/process/start_dir.hpp
@@ -0,0 +1,110 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROCESS_START_IN_DIR_HPP
+#define BOOST_PROCESS_START_IN_DIR_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/handler.hpp>
+#include <boost/process/locale.hpp>
+
+#if defined (BOOST_POSIX_API)
+#include <boost/process/detail/posix/start_dir.hpp>
+#elif defined (BOOST_WINDOWS_API)
+#include <boost/process/detail/windows/start_dir.hpp>
+#endif
+
+#include <boost/process/detail/config.hpp>
+#include <string>
+#include <boost/filesystem/path.hpp>
+
+/** \file boost/process/start_dir.hpp
+ *
+Header which provides the start_dir property, which allows to set the directory
+the process shall be started in.
+\xmlonly
+<programlisting>
+namespace boost {
+ namespace process {
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::start_dir">start_dir</globalname>;
+ }
+}
+</programlisting>
+\endxmlonly
+
+ */
+
+namespace boost { namespace process { namespace detail {
+
+struct start_dir_
+{
+ constexpr start_dir_() {};
+
+ template<typename Char>
+ api::start_dir_init<Char> operator()(const std::basic_string<Char> & st) const {return {st}; }
+ template<typename Char>
+ api::start_dir_init<Char> operator()(std::basic_string<Char> && s) const {return {std::move(s)}; }
+ template<typename Char>
+ api::start_dir_init<Char> operator()(const Char* s) const {return {s}; }
+ api::start_dir_init<typename boost::filesystem::path::value_type>
+ operator()(const boost::filesystem::path & st) const {return {st.native()}; }
+
+ template<typename Char>
+ api::start_dir_init<Char> operator= (const std::basic_string<Char> & st) const {return {st}; }
+ template<typename Char>
+ api::start_dir_init<Char> operator= (std::basic_string<Char> && s) const {return {std::move(s)}; }
+ template<typename Char>
+ api::start_dir_init<Char> operator= (const Char* s) const {return {s}; }
+ api::start_dir_init<typename boost::filesystem::path::value_type>
+ operator= (const boost::filesystem::path & st) const {return {st.native()}; }
+
+};
+
+template<> struct is_wchar_t<api::start_dir_init<wchar_t>> : std::true_type {};
+
+template<>
+struct char_converter<char, api::start_dir_init<wchar_t>>
+{
+ static api::start_dir_init<char> conv(const api::start_dir_init<wchar_t> & in)
+ {
+ return api::start_dir_init<char>{::boost::process::detail::convert(in.str())};
+ }
+};
+
+template<>
+struct char_converter<wchar_t, api::start_dir_init<char>>
+{
+ static api::start_dir_init<wchar_t> conv(const api::start_dir_init<char> & in)
+ {
+ return api::start_dir_init<wchar_t>{::boost::process::detail::convert(in.str())};
+ }
+};
+
+}
+
+/**
+
+To set the start dir, the `start_dir` property is provided.
+
+The valid operations are the following:
+
+\code{.cpp}
+start_dir=path
+start_dir(path)
+\endcode
+
+It can be used with `std::string`, `std::wstring` and `boost::filesystem::path`.
+
+
+ */
+constexpr ::boost::process::detail::start_dir_ start_dir;
+
+}}
+
+#endif
diff --git a/boost/process/system.hpp b/boost/process/system.hpp
new file mode 100644
index 0000000000..bdcac88713
--- /dev/null
+++ b/boost/process/system.hpp
@@ -0,0 +1,154 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the 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 boost/process/system.hpp
+ *
+ * Defines a system function.
+ */
+
+#ifndef BOOST_PROCESS_SYSTEM_HPP
+#define BOOST_PROCESS_SYSTEM_HPP
+
+#include <boost/process/detail/config.hpp>
+#include <boost/process/detail/on_exit.hpp>
+#include <boost/process/child.hpp>
+#include <boost/process/detail/async_handler.hpp>
+#include <boost/process/detail/execute_impl.hpp>
+#include <type_traits>
+#include <mutex>
+#include <condition_variable>
+
+#if defined(BOOST_POSIX_API)
+#include <boost/process/posix.hpp>
+#endif
+
+namespace boost {
+
+namespace process {
+
+namespace detail
+{
+
+struct system_impl_success_check : handler
+{
+ bool succeeded = false;
+
+ template<typename Exec>
+ void on_success(Exec &) { succeeded = true; }
+};
+
+template<typename IoService, typename ...Args>
+inline int system_impl(
+ std::true_type, /*needs ios*/
+ std::true_type, /*has io_service*/
+ Args && ...args)
+{
+ IoService & ios = ::boost::process::detail::get_io_service_var(args...);
+
+ system_impl_success_check check;
+
+ std::atomic_bool exited{false};
+
+ child c(std::forward<Args>(args)...,
+ check,
+ ::boost::process::on_exit(
+ [&](int, const std::error_code&)
+ {
+ ios.post([&]{exited.store(true);});
+ }));
+ if (!c.valid() || !check.succeeded)
+ return -1;
+
+ while (!exited.load())
+ ios.poll();
+
+ return c.exit_code();
+}
+
+template<typename IoService, typename ...Args>
+inline int system_impl(
+ std::true_type, /*needs ios */
+ std::false_type, /*has io_service*/
+ Args && ...args)
+{
+ IoService ios;
+ child c(ios, std::forward<Args>(args)...);
+ if (!c.valid())
+ return -1;
+
+ ios.run();
+ return c.exit_code();
+}
+
+
+template<typename IoService, typename ...Args>
+inline int system_impl(
+ std::false_type, /*needs ios*/
+ std::true_type, /*has io_service*/
+ Args && ...args)
+{
+ child c(std::forward<Args>(args)...);
+ if (!c.valid())
+ return -1;
+ c.wait();
+ return c.exit_code();
+}
+
+template<typename IoService, typename ...Args>
+inline int system_impl(
+ std::false_type, /*has async */
+ std::false_type, /*has io_service*/
+ Args && ...args)
+{
+ child c(std::forward<Args>(args)...
+#if defined(BOOST_POSIX_API)
+ ,::boost::process::posix::sig.dfl()
+#endif
+ );
+ if (!c.valid())
+ return -1;
+ c.wait();
+ return c.exit_code();
+}
+
+}
+
+/** Launches a process and waits for its exit.
+It works as std::system, though it allows
+all the properties boost.process provides. It will execute the process and wait for it's exit; then return the exit_code.
+
+\code{.cpp}
+int ret = system("ls");
+\endcode
+
+\attention Using this function with synchronous pipes leads to many potential deadlocks.
+
+When using this function with an asynchronous properties and NOT passing an io_service object,
+the system function will create one and run it. When the io_service is passed to the function,
+the system function will check if it is active, and call the io_service::run function if not.
+
+*/
+template<typename ...Args>
+inline int system(Args && ...args)
+{
+ typedef typename ::boost::process::detail::needs_io_service<Args...>::type
+ need_ios;
+ typedef typename ::boost::process::detail::has_io_service<Args...>::type
+ has_ios;
+ return ::boost::process::detail::system_impl<boost::asio::io_service>(
+ need_ios(), has_ios(),
+ std::forward<Args>(args)...);
+}
+
+
+}}
+#endif
+
diff --git a/boost/process/windows.hpp b/boost/process/windows.hpp
new file mode 100644
index 0000000000..3bc97a26aa
--- /dev/null
+++ b/boost/process/windows.hpp
@@ -0,0 +1,58 @@
+// Copyright (c) 2016 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_PROCESS_WINDOWS_HPP_
+#define BOOST_PROCESS_WINDOWS_HPP_
+
+#include <boost/process/detail/windows/show_window.hpp>
+
+/** \file boost/process/windows.hpp
+ *
+ * Header which provides the windows extensions.
+
+\xmlonly
+<programlisting>
+namespace boost {
+ namespace process {
+ namespace windows {
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::windows::hide">hide</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::windows::maximized">maximized</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::windows::minimized">minimized</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::windows::minimized_not_active">minimized_not_active</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::windows::not_active">not_active</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::windows::show">show</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::windows::show_normal">show_normal</globalname>;
+ }
+ }
+}
+</programlisting>
+ * \endxmlonly
+ * \warning Only available on windows.
+ * See the parameter documentation of [ShowWindow](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548.aspx) for more details.
+ */
+
+namespace boost { namespace process {
+
+///Namespace containing the windows exensions.
+namespace windows {
+
+///Hides the window and activates another window.
+constexpr ::boost::process::detail::windows::show_window<::boost::detail::winapi::SW_HIDE_ > hide;
+///Activates the window and displays it as a maximized window.
+constexpr ::boost::process::detail::windows::show_window<::boost::detail::winapi::SW_SHOWMAXIMIZED_ > maximized;
+///Activates the window and displays it as a minimized window.
+constexpr ::boost::process::detail::windows::show_window<::boost::detail::winapi::SW_SHOWMINIMIZED_ > minimized;
+///Displays the window as a minimized window. This value is similar to `minimized`, except the window is not activated.
+constexpr ::boost::process::detail::windows::show_window<::boost::detail::winapi::SW_SHOWMINNOACTIVE_> minimized_not_active;
+///Displays a window in its most recent size and position. This value is similar to show_normal`, except that the window is not activated.
+constexpr ::boost::process::detail::windows::show_window<::boost::detail::winapi::SW_SHOWNOACTIVATE_ > not_active;
+///Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
+constexpr ::boost::process::detail::windows::show_window<::boost::detail::winapi::SW_SHOWNORMAL_ > show;
+///Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
+constexpr ::boost::process::detail::windows::show_window<::boost::detail::winapi::SW_SHOWNORMAL_ > show_normal;
+
+
+}}}
+
+#endif /* BOOST_PROCESS_WINDOWS_HPP_ */
diff --git a/boost/python/converter/pyobject_type.hpp b/boost/python/converter/pyobject_type.hpp
index 526f9f9dba..bde39e8057 100644
--- a/boost/python/converter/pyobject_type.hpp
+++ b/boost/python/converter/pyobject_type.hpp
@@ -9,8 +9,11 @@
namespace boost { namespace python { namespace converter {
-BOOST_PYTHON_DECL PyObject* checked_downcast_impl(PyObject*, PyTypeObject*);
-
+BOOST_PYTHON_DECL inline
+PyObject* checked_downcast_impl(PyObject *obj, PyTypeObject *type)
+{
+ return (PyType_IsSubtype(Py_TYPE(obj), type) ? obj : NULL);
+}
// Used as a base class for specializations which need to provide
// Python type checking capability.
template <class Object, PyTypeObject* pytype>
diff --git a/boost/python/detail/config.hpp b/boost/python/detail/config.hpp
index 11c16308fb..c92ecb32b0 100644
--- a/boost/python/detail/config.hpp
+++ b/boost/python/detail/config.hpp
@@ -64,31 +64,18 @@
#endif
#if defined(BOOST_PYTHON_DYNAMIC_LIB)
-
-# if !defined(_WIN32) && !defined(__CYGWIN__) \
- && !defined(BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY) \
- && BOOST_WORKAROUND(__GNUC__, >= 3) && (__GNUC_MINOR__ >=5 || __GNUC__ > 3)
-# define BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY 1
-# endif
-
-# if BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY
+# if defined(BOOST_SYMBOL_EXPORT)
# if defined(BOOST_PYTHON_SOURCE)
-# define BOOST_PYTHON_DECL __attribute__ ((__visibility__("default")))
+# define BOOST_PYTHON_DECL BOOST_SYMBOL_EXPORT
+# define BOOST_PYTHON_DECL_FORWARD BOOST_SYMBOL_FORWARD_EXPORT
+# define BOOST_PYTHON_DECL_EXCEPTION BOOST_EXCEPTION_EXPORT
# define BOOST_PYTHON_BUILD_DLL
# else
-# define BOOST_PYTHON_DECL
-# endif
-# define BOOST_PYTHON_DECL_FORWARD
-# define BOOST_PYTHON_DECL_EXCEPTION __attribute__ ((__visibility__("default")))
-# elif (defined(_WIN32) || defined(__CYGWIN__))
-# if defined(BOOST_PYTHON_SOURCE)
-# define BOOST_PYTHON_DECL __declspec(dllexport)
-# define BOOST_PYTHON_BUILD_DLL
-# else
-# define BOOST_PYTHON_DECL __declspec(dllimport)
+# define BOOST_PYTHON_DECL BOOST_SYMBOL_IMPORT
+# define BOOST_PYTHON_DECL_FORWARD BOOST_SYMBOL_FORWARD_IMPORT
+# define BOOST_PYTHON_DECL_EXCEPTION BOOST_EXCEPTION_IMPORT
# endif
# endif
-
#endif
#ifndef BOOST_PYTHON_DECL
@@ -96,11 +83,11 @@
#endif
#ifndef BOOST_PYTHON_DECL_FORWARD
-# define BOOST_PYTHON_DECL_FORWARD BOOST_PYTHON_DECL
+# define BOOST_PYTHON_DECL_FORWARD
#endif
#ifndef BOOST_PYTHON_DECL_EXCEPTION
-# define BOOST_PYTHON_DECL_EXCEPTION BOOST_PYTHON_DECL
+# define BOOST_PYTHON_DECL_EXCEPTION
#endif
#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))
diff --git a/boost/python/detail/exception_handler.hpp b/boost/python/detail/exception_handler.hpp
index 7f49868be6..fdc9989836 100644
--- a/boost/python/detail/exception_handler.hpp
+++ b/boost/python/detail/exception_handler.hpp
@@ -11,7 +11,7 @@
namespace boost { namespace python { namespace detail {
-struct BOOST_PYTHON_DECL_FORWARD exception_handler;
+struct exception_handler;
typedef function2<bool, exception_handler const&, function0<void> const&> handler_function;
diff --git a/boost/python/detail/wrapper_base.hpp b/boost/python/detail/wrapper_base.hpp
index e5b93aa449..2a79e0c528 100755..100644
--- a/boost/python/detail/wrapper_base.hpp
+++ b/boost/python/detail/wrapper_base.hpp
@@ -14,7 +14,7 @@ class override;
namespace detail
{
- class BOOST_PYTHON_DECL_FORWARD wrapper_base;
+ class wrapper_base;
namespace wrapper_base_ // ADL disabler
{
diff --git a/boost/python/errors.hpp b/boost/python/errors.hpp
index 72960d9ea2..1eec6c2fe6 100644
--- a/boost/python/errors.hpp
+++ b/boost/python/errors.hpp
@@ -14,7 +14,7 @@
namespace boost { namespace python {
-struct BOOST_PYTHON_DECL_EXCEPTION error_already_set
+struct BOOST_PYTHON_DECL error_already_set
{
virtual ~error_already_set();
};
diff --git a/boost/python/numpy.hpp b/boost/python/numpy.hpp
index cd5876a8e4..18a6389d51 100644
--- a/boost/python/numpy.hpp
+++ b/boost/python/numpy.hpp
@@ -13,6 +13,7 @@
#include <boost/python/numpy/matrix.hpp>
#include <boost/python/numpy/ufunc.hpp>
#include <boost/python/numpy/invoke_matching.hpp>
+#include <boost/python/numpy/config.hpp>
namespace boost { namespace python { namespace numpy {
@@ -26,7 +27,7 @@ namespace boost { namespace python { namespace numpy {
* and "import_ufunc()", and then calls
* dtype::register_scalar_converters().
*/
-void initialize(bool register_scalar_converters=true);
+BOOST_NUMPY_DECL void initialize(bool register_scalar_converters=true);
}}} // namespace boost::python::numpy
diff --git a/boost/python/numpy/config.hpp b/boost/python/numpy/config.hpp
new file mode 100644
index 0000000000..6f39d3ce86
--- /dev/null
+++ b/boost/python/numpy/config.hpp
@@ -0,0 +1,78 @@
+// (C) Copyright Samuli-Petrus Korhonen 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)
+//
+// The author gratefully acknowleges the support of NMR Solutions, Inc., in
+// producing this work.
+
+// Revision History:
+// 15 Feb 17 Initial version
+
+#ifndef CONFIG_NUMPY20170215_H_
+# define CONFIG_NUMPY20170215_H_
+
+# include <boost/config.hpp>
+
+/*****************************************************************************
+ *
+ * Set up dll import/export options:
+ *
+ ****************************************************************************/
+
+// backwards compatibility:
+#ifdef BOOST_NUMPY_STATIC_LIB
+# define BOOST_NUMPY_STATIC_LINK
+# elif !defined(BOOST_NUMPY_DYNAMIC_LIB)
+# define BOOST_NUMPY_DYNAMIC_LIB
+#endif
+
+#if defined(BOOST_NUMPY_DYNAMIC_LIB)
+# if defined(BOOST_SYMBOL_EXPORT)
+# if defined(BOOST_NUMPY_SOURCE)
+# define BOOST_NUMPY_DECL BOOST_SYMBOL_EXPORT
+# define BOOST_NUMPY_DECL_FORWARD BOOST_SYMBOL_FORWARD_EXPORT
+# define BOOST_NUMPY_DECL_EXCEPTION BOOST_EXCEPTION_EXPORT
+# define BOOST_NUMPY_BUILD_DLL
+# else
+# define BOOST_NUMPY_DECL BOOST_SYMBOL_IMPORT
+# define BOOST_NUMPY_DECL_FORWARD BOOST_SYMBOL_FORWARD_IMPORT
+# define BOOST_NUMPY_DECL_EXCEPTION BOOST_EXCEPTION_IMPORT
+# endif
+# endif
+
+#endif
+
+#ifndef BOOST_NUMPY_DECL
+# define BOOST_NUMPY_DECL
+#endif
+
+#ifndef BOOST_NUMPY_DECL_FORWARD
+# define BOOST_NUMPY_DECL_FORWARD
+#endif
+
+#ifndef BOOST_NUMPY_DECL_EXCEPTION
+# define BOOST_NUMPY_DECL_EXCEPTION
+#endif
+
+// enable automatic library variant selection ------------------------------//
+
+#if !defined(BOOST_NUMPY_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_NUMPY_NO_LIB)
+//
+// 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 we're importing code from a dll, then tell auto_link.hpp about it:
+//
+#ifdef BOOST_NUMPY_DYNAMIC_LIB
+# define BOOST_DYN_LINK
+#endif
+//
+// And include the header that does the work:
+//
+#include <boost/config/auto_link.hpp>
+#endif // auto-linking disabled
+
+#endif // CONFIG_NUMPY20170215_H_
diff --git a/boost/python/numpy/dtype.hpp b/boost/python/numpy/dtype.hpp
index 1284f9e5d8..b9e95f9beb 100644
--- a/boost/python/numpy/dtype.hpp
+++ b/boost/python/numpy/dtype.hpp
@@ -14,6 +14,7 @@
#include <boost/python.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
+#include <boost/python/numpy/config.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/type_traits/add_pointer.hpp>
@@ -25,7 +26,7 @@ namespace boost { namespace python { namespace numpy {
*
* @todo This could have a lot more interesting accessors.
*/
-class dtype : public object {
+class BOOST_NUMPY_DECL dtype : public object {
static python::detail::new_reference convert(object::object_cref arg, bool align);
public:
@@ -55,7 +56,7 @@ public:
* This is more permissive than equality tests. For instance, if long and int are the same
* size, the dtypes corresponding to each will be equivalent, but not equal.
*/
- friend bool equivalent(dtype const & a, dtype const & b);
+ friend BOOST_NUMPY_DECL bool equivalent(dtype const & a, dtype const & b);
/**
* @brief Register from-Python converters for NumPy's built-in array scalar types.
@@ -69,7 +70,7 @@ public:
};
-bool equivalent(dtype const & a, dtype const & b);
+BOOST_NUMPY_DECL bool equivalent(dtype const & a, dtype const & b);
namespace detail
{
diff --git a/boost/python/numpy/invoke_matching.hpp b/boost/python/numpy/invoke_matching.hpp
index 90ec8ae2cb..095ca3a8db 100644
--- a/boost/python/numpy/invoke_matching.hpp
+++ b/boost/python/numpy/invoke_matching.hpp
@@ -19,7 +19,7 @@ namespace boost { namespace python { namespace numpy {
namespace detail
{
-struct add_pointer_meta
+struct BOOST_NUMPY_DECL add_pointer_meta
{
template <typename T>
struct apply
@@ -29,8 +29,8 @@ struct add_pointer_meta
};
-struct dtype_template_match_found {};
-struct nd_template_match_found {};
+struct BOOST_NUMPY_DECL dtype_template_match_found {};
+struct BOOST_NUMPY_DECL nd_template_match_found {};
template <typename Function>
struct dtype_template_invoker
diff --git a/boost/python/numpy/matrix.hpp b/boost/python/numpy/matrix.hpp
index af20e8f9be..829f544af5 100644
--- a/boost/python/numpy/matrix.hpp
+++ b/boost/python/numpy/matrix.hpp
@@ -14,6 +14,8 @@
#include <boost/python.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/ndarray.hpp>
+#include <boost/python/numpy/config.hpp>
+
namespace boost { namespace python { namespace numpy {
@@ -27,7 +29,7 @@ namespace boost { namespace python { namespace numpy {
* bad things happen when Python shuts down. I think this solution is safe, but I'd
* love to get that confirmed.
*/
-class matrix : public ndarray
+class BOOST_NUMPY_DECL matrix : public ndarray
{
static object construct(object_cref obj, dtype const & dt, bool copy);
static object construct(object_cref obj, bool copy);
diff --git a/boost/python/numpy/ndarray.hpp b/boost/python/numpy/ndarray.hpp
index 2985907b5b..e5b6a9e94b 100644
--- a/boost/python/numpy/ndarray.hpp
+++ b/boost/python/numpy/ndarray.hpp
@@ -16,6 +16,8 @@
#include <boost/type_traits/is_integral.hpp>
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/dtype.hpp>
+#include <boost/python/numpy/config.hpp>
+
#include <vector>
namespace boost { namespace python { namespace numpy {
@@ -26,7 +28,8 @@ namespace boost { namespace python { namespace numpy {
* @todo This could have a lot more functionality (like boost::python::numeric::array).
* Right now all that exists is what was needed to move raw data between C++ and Python.
*/
-class ndarray : public object
+
+class BOOST_NUMPY_DECL ndarray : public object
{
/**
@@ -139,32 +142,32 @@ public:
/**
* @brief Construct a new array with the given shape and data type, with data initialized to zero.
*/
-ndarray zeros(python::tuple const & shape, dtype const & dt);
-ndarray zeros(int nd, Py_intptr_t const * shape, dtype const & dt);
+BOOST_NUMPY_DECL ndarray zeros(python::tuple const & shape, dtype const & dt);
+BOOST_NUMPY_DECL ndarray zeros(int nd, Py_intptr_t const * shape, dtype const & dt);
/**
* @brief Construct a new array with the given shape and data type, with data left uninitialized.
*/
-ndarray empty(python::tuple const & shape, dtype const & dt);
-ndarray empty(int nd, Py_intptr_t const * shape, dtype const & dt);
+BOOST_NUMPY_DECL ndarray empty(python::tuple const & shape, dtype const & dt);
+BOOST_NUMPY_DECL ndarray empty(int nd, Py_intptr_t const * shape, dtype const & dt);
/**
* @brief Construct a new array from an arbitrary Python sequence.
*
* @todo This does't seem to handle ndarray subtypes the same way that "numpy.array" does in Python.
*/
-ndarray array(object const & obj);
-ndarray array(object const & obj, dtype const & dt);
+BOOST_NUMPY_DECL ndarray array(object const & obj);
+BOOST_NUMPY_DECL ndarray array(object const & obj, dtype const & dt);
namespace detail
{
-ndarray from_data_impl(void * data,
- dtype const & dt,
- std::vector<Py_intptr_t> const & shape,
- std::vector<Py_intptr_t> const & strides,
- object const & owner,
- bool writeable);
+BOOST_NUMPY_DECL ndarray from_data_impl(void * data,
+ dtype const & dt,
+ std::vector<Py_intptr_t> const & shape,
+ std::vector<Py_intptr_t> const & strides,
+ object const & owner,
+ bool writeable);
template <typename Container>
ndarray from_data_impl(void * data,
@@ -180,12 +183,12 @@ ndarray from_data_impl(void * data,
return from_data_impl(data, dt, shape_, strides_, owner, writeable);
}
-ndarray from_data_impl(void * data,
- dtype const & dt,
- object const & shape,
- object const & strides,
- object const & owner,
- bool writeable);
+BOOST_NUMPY_DECL ndarray from_data_impl(void * data,
+ dtype const & dt,
+ object const & shape,
+ object const & strides,
+ object const & owner,
+ bool writeable);
} // namespace boost::python::numpy::detail
@@ -247,39 +250,53 @@ inline ndarray from_data(void const * data,
* @param[in] nd_max Maximum number of dimensions.
* @param[in] flags Bitwise OR of flags specifying additional requirements.
*/
-ndarray from_object(object const & obj, dtype const & dt,
- int nd_min, int nd_max, ndarray::bitflag flags=ndarray::NONE);
-
-inline ndarray from_object(object const & obj, dtype const & dt,
- int nd, ndarray::bitflag flags=ndarray::NONE)
+BOOST_NUMPY_DECL ndarray from_object(object const & obj,
+ dtype const & dt,
+ int nd_min,
+ int nd_max,
+ ndarray::bitflag flags=ndarray::NONE);
+
+BOOST_NUMPY_DECL inline ndarray from_object(object const & obj,
+ dtype const & dt,
+ int nd,
+ ndarray::bitflag flags=ndarray::NONE)
{
return from_object(obj, dt, nd, nd, flags);
}
-inline ndarray from_object(object const & obj, dtype const & dt, ndarray::bitflag flags=ndarray::NONE)
+BOOST_NUMPY_DECL inline ndarray from_object(object const & obj,
+ dtype const & dt,
+ ndarray::bitflag flags=ndarray::NONE)
{
return from_object(obj, dt, 0, 0, flags);
}
-ndarray from_object(object const & obj, int nd_min, int nd_max,
- ndarray::bitflag flags=ndarray::NONE);
+BOOST_NUMPY_DECL ndarray from_object(object const & obj,
+ int nd_min,
+ int nd_max,
+ ndarray::bitflag flags=ndarray::NONE);
-inline ndarray from_object(object const & obj, int nd, ndarray::bitflag flags=ndarray::NONE)
+BOOST_NUMPY_DECL inline ndarray from_object(object const & obj,
+ int nd,
+ ndarray::bitflag flags=ndarray::NONE)
{
return from_object(obj, nd, nd, flags);
}
-inline ndarray from_object(object const & obj, ndarray::bitflag flags=ndarray::NONE)
+BOOST_NUMPY_DECL inline ndarray from_object(object const & obj,
+ ndarray::bitflag flags=ndarray::NONE)
{
return from_object(obj, 0, 0, flags);
}
-inline ndarray::bitflag operator|(ndarray::bitflag a, ndarray::bitflag b)
+BOOST_NUMPY_DECL inline ndarray::bitflag operator|(ndarray::bitflag a,
+ ndarray::bitflag b)
{
return ndarray::bitflag(int(a) | int(b));
}
-inline ndarray::bitflag operator&(ndarray::bitflag a, ndarray::bitflag b)
+BOOST_NUMPY_DECL inline ndarray::bitflag operator&(ndarray::bitflag a,
+ ndarray::bitflag b)
{
return ndarray::bitflag(int(a) & int(b));
}
diff --git a/boost/python/numpy/numpy_object_mgr_traits.hpp b/boost/python/numpy/numpy_object_mgr_traits.hpp
index 8f9f444074..a138f4cd52 100644
--- a/boost/python/numpy/numpy_object_mgr_traits.hpp
+++ b/boost/python/numpy/numpy_object_mgr_traits.hpp
@@ -7,6 +7,8 @@
#ifndef boost_python_numpy_numpy_object_mgr_traits_hpp_
#define boost_python_numpy_numpy_object_mgr_traits_hpp_
+#include <boost/python/numpy/config.hpp>
+
/**
* @brief Macro that specializes object_manager_traits by requiring a
* source-file implementation of get_pytype().
@@ -14,7 +16,7 @@
#define NUMPY_OBJECT_MANAGER_TRAITS(manager) \
template <> \
-struct object_manager_traits<manager> \
+struct BOOST_NUMPY_DECL object_manager_traits<manager> \
{ \
BOOST_STATIC_CONSTANT(bool, is_specialized = true); \
static inline python::detail::new_reference adopt(PyObject* x) \
diff --git a/boost/python/numpy/scalars.hpp b/boost/python/numpy/scalars.hpp
index 0ba23c41ac..c2a83d8253 100644
--- a/boost/python/numpy/scalars.hpp
+++ b/boost/python/numpy/scalars.hpp
@@ -22,7 +22,7 @@ namespace boost { namespace python { namespace numpy {
*
* @todo This could have a lot more functionality.
*/
-class void_ : public object
+class BOOST_NUMPY_DECL void_ : public object
{
static python::detail::new_reference convert(object_cref arg, bool align);
public:
diff --git a/boost/python/numpy/ufunc.hpp b/boost/python/numpy/ufunc.hpp
index 9262b37840..7e249238af 100644
--- a/boost/python/numpy/ufunc.hpp
+++ b/boost/python/numpy/ufunc.hpp
@@ -15,6 +15,7 @@
#include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/python/numpy/dtype.hpp>
#include <boost/python/numpy/ndarray.hpp>
+#include <boost/python/numpy/config.hpp>
namespace boost { namespace python { namespace numpy {
@@ -34,7 +35,7 @@ namespace boost { namespace python { namespace numpy {
* It's more dangerous than most object managers, however - maybe it actually belongs in
* a detail namespace?
*/
-class multi_iter : public object
+class BOOST_NUMPY_DECL multi_iter : public object
{
public:
@@ -61,13 +62,13 @@ public:
};
/// @brief Construct a multi_iter over a single sequence or scalar object.
-multi_iter make_multi_iter(object const & a1);
+BOOST_NUMPY_DECL multi_iter make_multi_iter(object const & a1);
/// @brief Construct a multi_iter by broadcasting two objects.
-multi_iter make_multi_iter(object const & a1, object const & a2);
+BOOST_NUMPY_DECL multi_iter make_multi_iter(object const & a1, object const & a2);
/// @brief Construct a multi_iter by broadcasting three objects.
-multi_iter make_multi_iter(object const & a1, object const & a2, object const & a3);
+BOOST_NUMPY_DECL multi_iter make_multi_iter(object const & a1, object const & a2, object const & a3);
/**
* @brief Helps wrap a C++ functor taking a single scalar argument as a broadcasting ufunc-like
diff --git a/boost/python/object/instance.hpp b/boost/python/object/instance.hpp
index 177576ef82..9c28d6822d 100644
--- a/boost/python/object/instance.hpp
+++ b/boost/python/object/instance.hpp
@@ -11,7 +11,7 @@
namespace boost { namespace python
{
- struct BOOST_PYTHON_DECL_FORWARD instance_holder;
+ struct instance_holder;
}} // namespace boost::python
namespace boost { namespace python { namespace objects {
diff --git a/boost/qvm/all.hpp b/boost/qvm/all.hpp
index b52a3339ba..73e8b81f27 100644
--- a/boost/qvm/all.hpp
+++ b/boost/qvm/all.hpp
@@ -9,20 +9,21 @@
#include <boost/qvm/error.hpp>
#include <boost/qvm/mat_operations.hpp>
#include <boost/qvm/mat_access.hpp>
-#include <boost/qvm/mat_index.hpp>
+#include <boost/qvm/mat_traits_defaults.hpp>
#include <boost/qvm/mat_traits_array.hpp>
#include <boost/qvm/map.hpp>
#include <boost/qvm/mat.hpp>
#include <boost/qvm/math.hpp>
#include <boost/qvm/quat_operations.hpp>
#include <boost/qvm/quat_access.hpp>
+#include <boost/qvm/quat_traits_defaults.hpp>
#include <boost/qvm/quat_traits.hpp>
#include <boost/qvm/quat.hpp>
#include <boost/qvm/quat_vec_operations.hpp>
#include <boost/qvm/swizzle.hpp>
#include <boost/qvm/vec_operations.hpp>
#include <boost/qvm/vec_access.hpp>
-#include <boost/qvm/vec_index.hpp>
+#include <boost/qvm/vec_traits_defaults.hpp>
#include <boost/qvm/vec_traits_array.hpp>
#include <boost/qvm/vec.hpp>
#include <boost/qvm/vec_mat_operations.hpp>
diff --git a/boost/qvm/detail/swizzle_traits.hpp b/boost/qvm/detail/swizzle_traits.hpp
index 4b304fa68c..8ead2976f5 100644
--- a/boost/qvm/detail/swizzle_traits.hpp
+++ b/boost/qvm/detail/swizzle_traits.hpp
@@ -184,6 +184,28 @@ boost
return r;
}
};
+
+ template <class OriginalType,class SwizzleList>
+ class
+ sws_
+ {
+ sws_( sws_ const & );
+ sws_ & operator=( sws_ const & );
+ ~sws_();
+
+ BOOST_QVM_STATIC_ASSERT((validate_swizzle_list<SwizzleList,1>::value));
+
+ public:
+
+ template <class R>
+ BOOST_QVM_INLINE_TRIVIAL
+ operator R() const
+ {
+ R r;
+ assign(r,*this);
+ return r;
+ }
+ };
}
template <class OriginalVector,class SwizzleList>
@@ -246,6 +268,43 @@ boost
}
};
+ template <class OriginalScalar,class SwizzleList>
+ struct
+ vec_traits<qvm_detail::sws_<OriginalScalar,SwizzleList> >
+ {
+ typedef qvm_detail::sws_<OriginalScalar,SwizzleList> this_vector;
+ typedef OriginalScalar scalar_type;
+ static int const dim=qvm_detail::swizzle_list_length<SwizzleList>::value;
+
+ template <int I>
+ static
+ BOOST_QVM_INLINE_CRITICAL
+ scalar_type
+ read_element( this_vector const & x )
+ {
+ BOOST_QVM_STATIC_ASSERT(I>=0);
+ BOOST_QVM_STATIC_ASSERT(I<dim);
+ int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
+ BOOST_QVM_STATIC_ASSERT(idx<1);
+ return idx==0?
+ reinterpret_cast<OriginalScalar const &>(x) :
+ qvm_detail::const_value<this_vector,idx>::value();
+ }
+
+ template <int I>
+ static
+ BOOST_QVM_INLINE_CRITICAL
+ scalar_type &
+ write_element( this_vector & x )
+ {
+ BOOST_QVM_STATIC_ASSERT(I>=0);
+ BOOST_QVM_STATIC_ASSERT(I<dim);
+ int const idx=qvm_detail::swizzle<SwizzleList,I>::value;
+ BOOST_QVM_STATIC_ASSERT(idx==0);
+ return reinterpret_cast<OriginalScalar &>(x);
+ }
+ };
+
template <class OriginalVector,class SwizzleList,int D>
struct
deduce_vec<qvm_detail::sw_<OriginalVector,SwizzleList>,D>
@@ -259,6 +318,20 @@ boost
{
typedef vec<typename vec_traits<OriginalVector>::scalar_type,D> type;
};
+
+ template <class Scalar,class SwizzleList,int D>
+ struct
+ deduce_vec<qvm_detail::sws_<Scalar,SwizzleList>,D>
+ {
+ typedef vec<Scalar,D> type;
+ };
+
+ template <class Scalar,class SwizzleList,int D>
+ struct
+ deduce_vec2<qvm_detail::sws_<Scalar,SwizzleList>,qvm_detail::sws_<Scalar,SwizzleList>,D>
+ {
+ typedef vec<Scalar,D> type;
+ };
}
}
diff --git a/boost/qvm/gen/mat_operations2.hpp b/boost/qvm/gen/mat_operations2.hpp
index 105ebde2ea..6fbda7a800 100644
--- a/boost/qvm/gen/mat_operations2.hpp
+++ b/boost/qvm/gen/mat_operations2.hpp
@@ -490,6 +490,42 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==2 && mat_traits<B>::cols==2,
+ deduce_mat<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a*mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<0,1>(r)=a*mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<R>::template write_element<1,0>(r)=a*mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<R>::template write_element<1,1>(r)=a*mat_traits<B>::template read_element<1,1>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator*;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct mul_sm_defined;
+
+ template <>
+ struct
+ mul_sm_defined<2,2>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
mat_traits<A>::rows==2 && mat_traits<A>::cols==1 && is_scalar<B>::value,
deduce_mat<A> >::type
operator*( A const & a, B b )
@@ -524,6 +560,40 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==2 && mat_traits<B>::cols==1,
+ deduce_mat<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a*mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<1,0>(r)=a*mat_traits<B>::template read_element<1,0>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator*;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct mul_sm_defined;
+
+ template <>
+ struct
+ mul_sm_defined<2,1>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
mat_traits<A>::rows==1 && mat_traits<A>::cols==2 && is_scalar<B>::value,
deduce_mat<A> >::type
operator*( A const & a, B b )
@@ -557,6 +627,40 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==1 && mat_traits<B>::cols==2,
+ deduce_mat<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a*mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<0,1>(r)=a*mat_traits<B>::template read_element<0,1>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator*;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct mul_sm_defined;
+
+ template <>
+ struct
+ mul_sm_defined<1,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<A>::cols==2 && is_scalar<B>::value,
A &>::type
@@ -692,6 +796,42 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==2 && mat_traits<B>::cols==2,
+ deduce_mat<B> >::type
+ operator/( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a/mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<0,1>(r)=a/mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<R>::template write_element<1,0>(r)=a/mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<R>::template write_element<1,1>(r)=a/mat_traits<B>::template read_element<1,1>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator/;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct div_sm_defined;
+
+ template <>
+ struct
+ div_sm_defined<2,2>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
mat_traits<A>::rows==2 && mat_traits<A>::cols==1 && is_scalar<B>::value,
deduce_mat<A> >::type
operator/( A const & a, B b )
@@ -726,6 +866,40 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==2 && mat_traits<B>::cols==1,
+ deduce_mat<B> >::type
+ operator/( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a/mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<1,0>(r)=a/mat_traits<B>::template read_element<1,0>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator/;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct div_sm_defined;
+
+ template <>
+ struct
+ div_sm_defined<2,1>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
mat_traits<A>::rows==1 && mat_traits<A>::cols==2 && is_scalar<B>::value,
deduce_mat<A> >::type
operator/( A const & a, B b )
diff --git a/boost/qvm/gen/mat_operations3.hpp b/boost/qvm/gen/mat_operations3.hpp
index 1458cf64d9..5b0e74b458 100644
--- a/boost/qvm/gen/mat_operations3.hpp
+++ b/boost/qvm/gen/mat_operations3.hpp
@@ -525,6 +525,47 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==3 && mat_traits<B>::cols==3,
+ deduce_mat<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a*mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<0,1>(r)=a*mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<R>::template write_element<0,2>(r)=a*mat_traits<B>::template read_element<0,2>(b);
+ mat_traits<R>::template write_element<1,0>(r)=a*mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<R>::template write_element<1,1>(r)=a*mat_traits<B>::template read_element<1,1>(b);
+ mat_traits<R>::template write_element<1,2>(r)=a*mat_traits<B>::template read_element<1,2>(b);
+ mat_traits<R>::template write_element<2,0>(r)=a*mat_traits<B>::template read_element<2,0>(b);
+ mat_traits<R>::template write_element<2,1>(r)=a*mat_traits<B>::template read_element<2,1>(b);
+ mat_traits<R>::template write_element<2,2>(r)=a*mat_traits<B>::template read_element<2,2>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator*;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct mul_sm_defined;
+
+ template <>
+ struct
+ mul_sm_defined<3,3>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
mat_traits<A>::rows==3 && mat_traits<A>::cols==1 && is_scalar<B>::value,
deduce_mat<A> >::type
operator*( A const & a, B b )
@@ -560,6 +601,41 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==3 && mat_traits<B>::cols==1,
+ deduce_mat<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a*mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<1,0>(r)=a*mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<R>::template write_element<2,0>(r)=a*mat_traits<B>::template read_element<2,0>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator*;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct mul_sm_defined;
+
+ template <>
+ struct
+ mul_sm_defined<3,1>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
mat_traits<A>::rows==1 && mat_traits<A>::cols==3 && is_scalar<B>::value,
deduce_mat<A> >::type
operator*( A const & a, B b )
@@ -594,6 +670,41 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==1 && mat_traits<B>::cols==3,
+ deduce_mat<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a*mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<0,1>(r)=a*mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<R>::template write_element<0,2>(r)=a*mat_traits<B>::template read_element<0,2>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator*;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct mul_sm_defined;
+
+ template <>
+ struct
+ mul_sm_defined<1,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<A>::cols==3 && is_scalar<B>::value,
A &>::type
@@ -741,6 +852,47 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==3 && mat_traits<B>::cols==3,
+ deduce_mat<B> >::type
+ operator/( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a/mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<0,1>(r)=a/mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<R>::template write_element<0,2>(r)=a/mat_traits<B>::template read_element<0,2>(b);
+ mat_traits<R>::template write_element<1,0>(r)=a/mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<R>::template write_element<1,1>(r)=a/mat_traits<B>::template read_element<1,1>(b);
+ mat_traits<R>::template write_element<1,2>(r)=a/mat_traits<B>::template read_element<1,2>(b);
+ mat_traits<R>::template write_element<2,0>(r)=a/mat_traits<B>::template read_element<2,0>(b);
+ mat_traits<R>::template write_element<2,1>(r)=a/mat_traits<B>::template read_element<2,1>(b);
+ mat_traits<R>::template write_element<2,2>(r)=a/mat_traits<B>::template read_element<2,2>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator/;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct div_sm_defined;
+
+ template <>
+ struct
+ div_sm_defined<3,3>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
mat_traits<A>::rows==3 && mat_traits<A>::cols==1 && is_scalar<B>::value,
deduce_mat<A> >::type
operator/( A const & a, B b )
@@ -776,6 +928,41 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==3 && mat_traits<B>::cols==1,
+ deduce_mat<B> >::type
+ operator/( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a/mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<1,0>(r)=a/mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<R>::template write_element<2,0>(r)=a/mat_traits<B>::template read_element<2,0>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator/;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct div_sm_defined;
+
+ template <>
+ struct
+ div_sm_defined<3,1>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
mat_traits<A>::rows==1 && mat_traits<A>::cols==3 && is_scalar<B>::value,
deduce_mat<A> >::type
operator/( A const & a, B b )
diff --git a/boost/qvm/gen/mat_operations4.hpp b/boost/qvm/gen/mat_operations4.hpp
index 0dab7fba9f..ad115f916d 100644
--- a/boost/qvm/gen/mat_operations4.hpp
+++ b/boost/qvm/gen/mat_operations4.hpp
@@ -568,6 +568,54 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==4 && mat_traits<B>::cols==4,
+ deduce_mat<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a*mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<0,1>(r)=a*mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<R>::template write_element<0,2>(r)=a*mat_traits<B>::template read_element<0,2>(b);
+ mat_traits<R>::template write_element<0,3>(r)=a*mat_traits<B>::template read_element<0,3>(b);
+ mat_traits<R>::template write_element<1,0>(r)=a*mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<R>::template write_element<1,1>(r)=a*mat_traits<B>::template read_element<1,1>(b);
+ mat_traits<R>::template write_element<1,2>(r)=a*mat_traits<B>::template read_element<1,2>(b);
+ mat_traits<R>::template write_element<1,3>(r)=a*mat_traits<B>::template read_element<1,3>(b);
+ mat_traits<R>::template write_element<2,0>(r)=a*mat_traits<B>::template read_element<2,0>(b);
+ mat_traits<R>::template write_element<2,1>(r)=a*mat_traits<B>::template read_element<2,1>(b);
+ mat_traits<R>::template write_element<2,2>(r)=a*mat_traits<B>::template read_element<2,2>(b);
+ mat_traits<R>::template write_element<2,3>(r)=a*mat_traits<B>::template read_element<2,3>(b);
+ mat_traits<R>::template write_element<3,0>(r)=a*mat_traits<B>::template read_element<3,0>(b);
+ mat_traits<R>::template write_element<3,1>(r)=a*mat_traits<B>::template read_element<3,1>(b);
+ mat_traits<R>::template write_element<3,2>(r)=a*mat_traits<B>::template read_element<3,2>(b);
+ mat_traits<R>::template write_element<3,3>(r)=a*mat_traits<B>::template read_element<3,3>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator*;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct mul_sm_defined;
+
+ template <>
+ struct
+ mul_sm_defined<4,4>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
mat_traits<A>::rows==4 && mat_traits<A>::cols==1 && is_scalar<B>::value,
deduce_mat<A> >::type
operator*( A const & a, B b )
@@ -604,6 +652,42 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==4 && mat_traits<B>::cols==1,
+ deduce_mat<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a*mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<1,0>(r)=a*mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<R>::template write_element<2,0>(r)=a*mat_traits<B>::template read_element<2,0>(b);
+ mat_traits<R>::template write_element<3,0>(r)=a*mat_traits<B>::template read_element<3,0>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator*;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct mul_sm_defined;
+
+ template <>
+ struct
+ mul_sm_defined<4,1>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
mat_traits<A>::rows==1 && mat_traits<A>::cols==4 && is_scalar<B>::value,
deduce_mat<A> >::type
operator*( A const & a, B b )
@@ -639,6 +723,42 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==1 && mat_traits<B>::cols==4,
+ deduce_mat<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a*mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<0,1>(r)=a*mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<R>::template write_element<0,2>(r)=a*mat_traits<B>::template read_element<0,2>(b);
+ mat_traits<R>::template write_element<0,3>(r)=a*mat_traits<B>::template read_element<0,3>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator*;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct mul_sm_defined;
+
+ template <>
+ struct
+ mul_sm_defined<1,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<A>::cols==4 && is_scalar<B>::value,
A &>::type
@@ -802,6 +922,54 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==4 && mat_traits<B>::cols==4,
+ deduce_mat<B> >::type
+ operator/( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a/mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<0,1>(r)=a/mat_traits<B>::template read_element<0,1>(b);
+ mat_traits<R>::template write_element<0,2>(r)=a/mat_traits<B>::template read_element<0,2>(b);
+ mat_traits<R>::template write_element<0,3>(r)=a/mat_traits<B>::template read_element<0,3>(b);
+ mat_traits<R>::template write_element<1,0>(r)=a/mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<R>::template write_element<1,1>(r)=a/mat_traits<B>::template read_element<1,1>(b);
+ mat_traits<R>::template write_element<1,2>(r)=a/mat_traits<B>::template read_element<1,2>(b);
+ mat_traits<R>::template write_element<1,3>(r)=a/mat_traits<B>::template read_element<1,3>(b);
+ mat_traits<R>::template write_element<2,0>(r)=a/mat_traits<B>::template read_element<2,0>(b);
+ mat_traits<R>::template write_element<2,1>(r)=a/mat_traits<B>::template read_element<2,1>(b);
+ mat_traits<R>::template write_element<2,2>(r)=a/mat_traits<B>::template read_element<2,2>(b);
+ mat_traits<R>::template write_element<2,3>(r)=a/mat_traits<B>::template read_element<2,3>(b);
+ mat_traits<R>::template write_element<3,0>(r)=a/mat_traits<B>::template read_element<3,0>(b);
+ mat_traits<R>::template write_element<3,1>(r)=a/mat_traits<B>::template read_element<3,1>(b);
+ mat_traits<R>::template write_element<3,2>(r)=a/mat_traits<B>::template read_element<3,2>(b);
+ mat_traits<R>::template write_element<3,3>(r)=a/mat_traits<B>::template read_element<3,3>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator/;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct div_sm_defined;
+
+ template <>
+ struct
+ div_sm_defined<4,4>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
mat_traits<A>::rows==4 && mat_traits<A>::cols==1 && is_scalar<B>::value,
deduce_mat<A> >::type
operator/( A const & a, B b )
@@ -838,6 +1006,42 @@ boost
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename lazy_enable_if_c<
+ is_scalar<A>::value && mat_traits<B>::rows==4 && mat_traits<B>::cols==1,
+ deduce_mat<B> >::type
+ operator/( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ mat_traits<R>::template write_element<0,0>(r)=a/mat_traits<B>::template read_element<0,0>(b);
+ mat_traits<R>::template write_element<1,0>(r)=a/mat_traits<B>::template read_element<1,0>(b);
+ mat_traits<R>::template write_element<2,0>(r)=a/mat_traits<B>::template read_element<2,0>(b);
+ mat_traits<R>::template write_element<3,0>(r)=a/mat_traits<B>::template read_element<3,0>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator/;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int R,int C>
+ struct div_sm_defined;
+
+ template <>
+ struct
+ div_sm_defined<4,1>
+ {
+ static bool const value=true;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
mat_traits<A>::rows==1 && mat_traits<A>::cols==4 && is_scalar<B>::value,
deduce_mat<A> >::type
operator/( A const & a, B b )
diff --git a/boost/qvm/gen/swizzle2.hpp b/boost/qvm/gen/swizzle2.hpp
index fd953d3812..b894bb6986 100644
--- a/boost/qvm/gen/swizzle2.hpp
+++ b/boost/qvm/gen/swizzle2.hpp
@@ -93,6 +93,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > const &>::type
+ X1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -102,6 +111,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > &>::type
+ X1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > &>(a);
+ }
BOOST_QVM_INLINE_TRIVIAL
qvm_detail::sw01_<qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > const &
_10()
@@ -177,6 +195,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > const &>::type
+ X0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -186,6 +213,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > &>::type
+ X0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -519,6 +555,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > const &>::type
+ _1X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -528,6 +573,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > &>::type
+ _1X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -537,6 +591,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > const &>::type
+ _0X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -546,6 +609,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > &>::type
+ _0X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -609,6 +681,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > const &>::type
+ XX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -618,6 +699,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > &>::type
+ XX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > &>(a);
+ }
}
}
diff --git a/boost/qvm/gen/swizzle3.hpp b/boost/qvm/gen/swizzle3.hpp
index 30a24c3a35..f1f182d2bd 100644
--- a/boost/qvm/gen/swizzle3.hpp
+++ b/boost/qvm/gen/swizzle3.hpp
@@ -93,6 +93,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > const &>::type
+ X11( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -102,6 +111,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > &>::type
+ X11( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > &>(a);
+ }
BOOST_QVM_INLINE_TRIVIAL
qvm_detail::sw01_<qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > const &
_101()
@@ -177,6 +195,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > const &>::type
+ X01( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -186,6 +213,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > &>::type
+ X01( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -519,6 +555,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > const &>::type
+ _1X1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -528,6 +573,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > &>::type
+ _1X1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -537,6 +591,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > const &>::type
+ _0X1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -546,6 +609,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > &>::type
+ _0X1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -609,6 +681,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > const &>::type
+ XX1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -618,6 +699,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > &>::type
+ XX1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > &>(a);
+ }
BOOST_QVM_INLINE_TRIVIAL
qvm_detail::sw01_<qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > const &
_110()
@@ -693,6 +783,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > const &>::type
+ X10( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -702,6 +801,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > &>::type
+ X10( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > &>(a);
+ }
BOOST_QVM_INLINE_TRIVIAL
qvm_detail::sw01_<qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > const &
_100()
@@ -777,6 +885,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > const &>::type
+ X00( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -786,6 +903,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > &>::type
+ X00( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -1119,6 +1245,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > const &>::type
+ _1X0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -1128,6 +1263,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > &>::type
+ _1X0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -1137,6 +1281,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > const &>::type
+ _0X0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -1146,6 +1299,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > &>::type
+ _0X0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -1209,6 +1371,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > const &>::type
+ XX0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -1218,6 +1389,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > &>::type
+ XX0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3171,6 +3351,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > const &>::type
+ _11X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3180,6 +3369,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > &>::type
+ _11X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3189,6 +3387,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > const &>::type
+ _01X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3198,6 +3405,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > &>::type
+ _01X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3261,6 +3477,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > const &>::type
+ X1X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3270,6 +3495,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > &>::type
+ X1X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3279,6 +3513,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > const &>::type
+ _10X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3288,6 +3531,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > &>::type
+ _10X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3297,6 +3549,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > const &>::type
+ _00X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3306,6 +3567,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > &>::type
+ _00X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3369,6 +3639,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > const &>::type
+ X0X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3378,6 +3657,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > &>::type
+ X0X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3711,6 +3999,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > const &>::type
+ _1XX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3720,6 +4017,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > &>::type
+ _1XX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3729,6 +4035,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > const &>::type
+ _0XX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3738,6 +4053,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > &>::type
+ _0XX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3801,6 +4125,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > const &>::type
+ XXX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3810,6 +4143,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > &>::type
+ XXX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > &>(a);
+ }
}
}
diff --git a/boost/qvm/gen/swizzle4.hpp b/boost/qvm/gen/swizzle4.hpp
index db10e2a3b6..91ba215c8b 100644
--- a/boost/qvm/gen/swizzle4.hpp
+++ b/boost/qvm/gen/swizzle4.hpp
@@ -93,6 +93,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ X111( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -102,6 +111,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ X111( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
BOOST_QVM_INLINE_TRIVIAL
qvm_detail::sw01_<qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &
_1011()
@@ -177,6 +195,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ X011( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -186,6 +213,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ X011( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -519,6 +555,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ _1X11( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -528,6 +573,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ _1X11( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -537,6 +591,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ _0X11( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -546,6 +609,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ _0X11( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -609,6 +681,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ XX11( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -618,6 +699,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ XX11( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
BOOST_QVM_INLINE_TRIVIAL
qvm_detail::sw01_<qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &
_1101()
@@ -693,6 +783,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ X101( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -702,6 +801,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ X101( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
BOOST_QVM_INLINE_TRIVIAL
qvm_detail::sw01_<qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &
_1001()
@@ -777,6 +885,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ X001( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -786,6 +903,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ X001( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -1119,6 +1245,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ _1X01( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -1128,6 +1263,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ _1X01( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -1137,6 +1281,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ _0X01( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -1146,6 +1299,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ _0X01( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -1209,6 +1371,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ XX01( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -1218,6 +1389,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ XX01( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3171,6 +3351,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ _11X1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3180,6 +3369,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ _11X1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3189,6 +3387,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ _01X1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3198,6 +3405,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ _01X1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3261,6 +3477,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ X1X1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3270,6 +3495,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ X1X1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3279,6 +3513,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ _10X1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3288,6 +3531,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ _10X1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3297,6 +3549,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ _00X1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3306,6 +3567,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ _00X1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3369,6 +3639,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ X0X1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3378,6 +3657,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ X0X1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3711,6 +3999,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ _1XX1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3720,6 +4017,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ _1XX1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3729,6 +4035,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ _0XX1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3738,6 +4053,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ _0XX1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3801,6 +4125,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>::type
+ XXX1( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3810,6 +4143,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>::type
+ XXX1( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2 > > > > > &>(a);
+ }
BOOST_QVM_INLINE_TRIVIAL
qvm_detail::sw01_<qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &
_1110()
@@ -3885,6 +4227,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ X110( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3894,6 +4245,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ X110( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
BOOST_QVM_INLINE_TRIVIAL
qvm_detail::sw01_<qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &
_1010()
@@ -3969,6 +4329,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ X010( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -3978,6 +4347,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ X010( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -4311,6 +4689,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ _1X10( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -4320,6 +4707,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ _1X10( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -4329,6 +4725,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ _0X10( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -4338,6 +4743,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ _0X10( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -4401,6 +4815,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ XX10( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -4410,6 +4833,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ XX10( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
BOOST_QVM_INLINE_TRIVIAL
qvm_detail::sw01_<qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &
_1100()
@@ -4485,6 +4917,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ X100( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -4494,6 +4935,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ X100( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
BOOST_QVM_INLINE_TRIVIAL
qvm_detail::sw01_<qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &
_1000()
@@ -4569,6 +5019,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ X000( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -4578,6 +5037,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ X000( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -4911,6 +5379,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ _1X00( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -4920,6 +5397,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ _1X00( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -4929,6 +5415,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ _0X00( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -4938,6 +5433,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ _0X00( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -5001,6 +5505,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ XX00( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -5010,6 +5523,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ XX00( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -6963,6 +7485,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ _11X0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -6972,6 +7503,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ _11X0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -6981,6 +7521,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ _01X0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -6990,6 +7539,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ _01X0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7053,6 +7611,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ X1X0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7062,6 +7629,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ X1X0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7071,6 +7647,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ _10X0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7080,6 +7665,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ _10X0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7089,6 +7683,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ _00X0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7098,6 +7701,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ _00X0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7161,6 +7773,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ X0X0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7170,6 +7791,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ X0X0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7503,6 +8133,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ _1XX0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7512,6 +8151,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ _1XX0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7521,6 +8169,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ _0XX0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7530,6 +8187,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ _0XX0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7593,6 +8259,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>::type
+ XXX0( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -7602,6 +8277,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>::type
+ XXX0( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19275,6 +19959,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _111X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19284,6 +19977,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _111X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19293,6 +19995,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _011X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19302,6 +20013,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _011X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19365,6 +20085,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ X11X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19374,6 +20103,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ X11X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19383,6 +20121,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _101X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19392,6 +20139,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _101X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19401,6 +20157,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _001X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19410,6 +20175,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _001X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19473,6 +20247,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ X01X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19482,6 +20265,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ X01X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19815,6 +20607,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _1X1X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19824,6 +20625,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _1X1X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19833,6 +20643,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _0X1X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19842,6 +20661,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _0X1X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19905,6 +20733,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ XX1X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19914,6 +20751,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ XX1X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19923,6 +20769,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _110X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19932,6 +20787,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _110X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19941,6 +20805,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _010X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -19950,6 +20823,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _010X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20013,6 +20895,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ X10X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20022,6 +20913,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ X10X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20031,6 +20931,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _100X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20040,6 +20949,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _100X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20049,6 +20967,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _000X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20058,6 +20985,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _000X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20121,6 +21057,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ X00X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20130,6 +21075,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ X00X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20463,6 +21417,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _1X0X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20472,6 +21435,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _1X0X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20481,6 +21453,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _0X0X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20490,6 +21471,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _0X0X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20553,6 +21543,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ XX0X( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -20562,6 +21561,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ XX0X( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -22515,6 +23523,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _11XX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -22524,6 +23541,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _11XX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -22533,6 +23559,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _01XX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -22542,6 +23577,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _01XX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -22605,6 +23649,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ X1XX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -22614,6 +23667,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ X1XX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -22623,6 +23685,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _10XX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -22632,6 +23703,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _10XX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -22641,6 +23721,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _00XX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -22650,6 +23739,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _00XX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -22713,6 +23811,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ X0XX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -22722,6 +23829,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ X0XX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -23055,6 +24171,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _1XXX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -23064,6 +24189,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _1XXX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-2,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -23073,6 +24207,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ _0XXX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -23082,6 +24225,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ _0XXX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<-1,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -23145,6 +24297,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>::type
+ XXXX( S const & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > const &>(a);
+ }
template <class V>
BOOST_QVM_INLINE_TRIVIAL
typename enable_if_c<
@@ -23154,6 +24315,15 @@ boost
{
return reinterpret_cast<qvm_detail::sw_<V,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
}
+ template <class S>
+ BOOST_QVM_INLINE_TRIVIAL
+ typename enable_if_c<
+ is_scalar<S>::value,
+ qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>::type
+ XXXX( S & a )
+ {
+ return reinterpret_cast<qvm_detail::sws_<S,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0,qvm_detail::swizzle_idx<0 > > > > > &>(a);
+ }
}
}
diff --git a/boost/qvm/gen/vec_operations2.hpp b/boost/qvm/gen/vec_operations2.hpp
index 715aec5bdd..00ee6d6eb5 100644
--- a/boost/qvm/gen/vec_operations2.hpp
+++ b/boost/qvm/gen/vec_operations2.hpp
@@ -192,6 +192,40 @@ boost
};
}
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
+ is_scalar<A>::value && vec_traits<B>::dim==2,
+ deduce_vec<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_vec<B>::type R;
+ R r;
+ vec_traits<R>::template write_element<0>(r)=a*vec_traits<B>::template read_element<0>(b);
+ vec_traits<R>::template write_element<1>(r)=a*vec_traits<B>::template read_element<1>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator*;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int D>
+ struct mul_sv_defined;
+
+ template <>
+ struct
+ mul_sv_defined<2>
+ {
+ static bool const value=true;
+ };
+ }
+
template <class A,class B>
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 405848fd85..d894066efc 100644
--- a/boost/qvm/gen/vec_operations3.hpp
+++ b/boost/qvm/gen/vec_operations3.hpp
@@ -197,6 +197,41 @@ boost
};
}
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
+ is_scalar<A>::value && vec_traits<B>::dim==3,
+ deduce_vec<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_vec<B>::type R;
+ R r;
+ vec_traits<R>::template write_element<0>(r)=a*vec_traits<B>::template read_element<0>(b);
+ vec_traits<R>::template write_element<1>(r)=a*vec_traits<B>::template read_element<1>(b);
+ vec_traits<R>::template write_element<2>(r)=a*vec_traits<B>::template read_element<2>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator*;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int D>
+ struct mul_sv_defined;
+
+ template <>
+ struct
+ mul_sv_defined<3>
+ {
+ static bool const value=true;
+ };
+ }
+
template <class A,class B>
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 ac7c8e4c62..91049445a9 100644
--- a/boost/qvm/gen/vec_operations4.hpp
+++ b/boost/qvm/gen/vec_operations4.hpp
@@ -202,6 +202,42 @@ boost
};
}
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
+ is_scalar<A>::value && vec_traits<B>::dim==4,
+ deduce_vec<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_vec<B>::type R;
+ R r;
+ vec_traits<R>::template write_element<0>(r)=a*vec_traits<B>::template read_element<0>(b);
+ vec_traits<R>::template write_element<1>(r)=a*vec_traits<B>::template read_element<1>(b);
+ vec_traits<R>::template write_element<2>(r)=a*vec_traits<B>::template read_element<2>(b);
+ vec_traits<R>::template write_element<3>(r)=a*vec_traits<B>::template read_element<3>(b);
+ return r;
+ }
+
+ namespace
+ sfinae
+ {
+ using ::boost::qvm::operator*;
+ }
+
+ namespace
+ qvm_detail
+ {
+ template <int D>
+ struct mul_sv_defined;
+
+ template <>
+ struct
+ mul_sv_defined<4>
+ {
+ static bool const value=true;
+ };
+ }
+
template <class A,class B>
BOOST_QVM_INLINE_OPERATIONS
typename enable_if_c<
diff --git a/boost/qvm/mat_index.hpp b/boost/qvm/mat_index.hpp
deleted file mode 100644
index e7bcdad1e5..0000000000
--- a/boost/qvm/mat_index.hpp
+++ /dev/null
@@ -1,145 +0,0 @@
-//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_90273D9C0E5911E281B7981F6288709B
-#define UUID_90273D9C0E5911E281B7981F6288709B
-
-#include <boost/qvm/mat_traits.hpp>
-#include <boost/qvm/inline.hpp>
-#include <boost/qvm/assert.hpp>
-#include <boost/qvm/enable_if.hpp>
-#include <boost/qvm/error.hpp>
-#include <boost/exception/info.hpp>
-
-namespace
-boost
- {
- namespace
- qvm
- {
- ////////////////////////////////////////////////
-
- namespace
- qvm_detail
- {
- template <int R,int C>
- struct
- mat_index_read_defined
- {
- static bool const value=false;
- };
-
- template <int I,int N>
- struct
- matrix_r
- {
- template <class A>
- static
- BOOST_QVM_INLINE_CRITICAL
- typename mat_traits<A>::scalar_type
- read_element_idx( A const & a, int r, int c )
- {
- return (I/mat_traits<A>::cols)==r && (I%mat_traits<A>::cols)==c?
- mat_traits<A>::template read_element<I/mat_traits<A>::cols,I%mat_traits<A>::cols>(a) :
- matrix_r<I+1,N>::read_element_idx(a,r,c);
- }
- };
-
- template <int N>
- struct
- matrix_r<N,N>
- {
- template <class A>
- static
- BOOST_QVM_INLINE_TRIVIAL
- typename mat_traits<A>::scalar_type
- read_element_idx( A const & a, int, int )
- {
- BOOST_QVM_ASSERT(0);
- return mat_traits<A>::template read_element<0,0>(a);
- }
- };
- }
-
- template <class A>
- BOOST_QVM_INLINE_TRIVIAL
- typename boost::enable_if_c<
- is_mat<A>::value &&
- !qvm_detail::mat_index_read_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
- typename mat_traits<A>::scalar_type>::type
- mat_index_read( A const & a, int r, int c )
- {
- return qvm_detail::matrix_r<0,mat_traits<A>::rows*mat_traits<A>::cols>::read_element_idx(a,r,c);
- }
-
- ////////////////////////////////////////////////
-
- namespace
- qvm_detail
- {
- template <int R,int C>
- struct
- mat_index_write_defined
- {
- static bool const value=false;
- };
-
- template <int I,int N>
- struct
- matrix_w
- {
- template <class A>
- static
- BOOST_QVM_INLINE_CRITICAL
- typename mat_traits<A>::scalar_type &
- write_element_idx( A & a, int r, int c )
- {
- return (I/mat_traits<A>::cols)==r && (I%mat_traits<A>::cols)==c?
- mat_traits<A>::template write_element<I/mat_traits<A>::cols,I%mat_traits<A>::cols>(a) :
- matrix_w<I+1,N>::write_element_idx(a,r,c);
- }
- };
-
- template <int N>
- struct
- matrix_w<N,N>
- {
- template <class A>
- static
- BOOST_QVM_INLINE_TRIVIAL
- typename mat_traits<A>::scalar_type &
- write_element_idx( A & a, int, int )
- {
- BOOST_QVM_ASSERT(0);
- return mat_traits<A>::template write_element<0,0>(a);
- }
- };
- }
-
- template <class A>
- BOOST_QVM_INLINE_TRIVIAL
- typename boost::enable_if_c<
- is_mat<A>::value &&
- !qvm_detail::mat_index_write_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
- typename mat_traits<A>::scalar_type &>::type
- mat_index_write( A & a, int r, int c )
- {
- return qvm_detail::matrix_w<0,mat_traits<A>::rows*mat_traits<A>::cols>::write_element_idx(a,r,c);
- }
-
- ////////////////////////////////////////////////
-
- namespace
- sfinae
- {
- using ::boost::qvm::mat_index_read;
- using ::boost::qvm::mat_index_write;
- }
-
- ////////////////////////////////////////////////
- }
- }
-
-#endif
diff --git a/boost/qvm/mat_operations.hpp b/boost/qvm/mat_operations.hpp
index 46eaba5efe..0ec221ccff 100644
--- a/boost/qvm/mat_operations.hpp
+++ b/boost/qvm/mat_operations.hpp
@@ -823,6 +823,35 @@ boost
{
template <int M,int N>
struct
+ mul_sm_defined
+ {
+ static bool const value=false;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
+ is_scalar<A>::value && is_mat<B>::value &&
+ !qvm_detail::mul_sm_defined<mat_traits<B>::rows,mat_traits<B>::cols>::value,
+ deduce_mat<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_mat<B>::type R;
+ R r;
+ for( int i=0; i!=mat_traits<B>::rows; ++i )
+ for( int j=0; j!=mat_traits<B>::cols; ++j )
+ mat_traits<R>::write_element_idx(i,j,r)=a*mat_traits<B>::read_element_idx(i,j,b);
+ return r;
+ }
+
+ ////////////////////////////////////////////////
+
+ namespace
+ qvm_detail
+ {
+ template <int M,int N>
+ struct
neq_mm_defined
{
static bool const value=false;
@@ -1067,7 +1096,7 @@ boost
static
BOOST_QVM_INLINE_CRITICAL
scalar_type
- read_element( this_matrix const & x )
+ read_element( this_matrix const & )
{
BOOST_QVM_STATIC_ASSERT(Row>=0);
BOOST_QVM_STATIC_ASSERT(Row<Rows);
@@ -1079,7 +1108,7 @@ boost
static
BOOST_QVM_INLINE_CRITICAL
scalar_type
- read_element_idx( int row, int col, this_matrix const & x )
+ read_element_idx( int row, int col, this_matrix const & )
{
BOOST_QVM_ASSERT(row>=0);
BOOST_QVM_ASSERT(row<rows);
diff --git a/boost/qvm/mat_traits_defaults.hpp b/boost/qvm/mat_traits_defaults.hpp
new file mode 100644
index 0000000000..898e79064a
--- /dev/null
+++ b/boost/qvm/mat_traits_defaults.hpp
@@ -0,0 +1,95 @@
+//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_FB4D5BEAC71B11E68D0EEF1707624D53
+#define UUID_FB4D5BEAC71B11E68D0EEF1707624D53
+
+#include <boost/qvm/inline.hpp>
+#include <boost/qvm/assert.hpp>
+
+namespace
+boost
+ {
+ namespace
+ qvm
+ {
+ template <class>
+ struct mat_traits;
+
+ namespace
+ qvm_detail
+ {
+ template <int I,int N>
+ struct
+ matrix_w
+ {
+ template <class A>
+ static
+ BOOST_QVM_INLINE_CRITICAL
+ typename mat_traits<A>::scalar_type &
+ write_element_idx( int r, int c, A & a )
+ {
+ return (I/mat_traits<A>::cols)==r && (I%mat_traits<A>::cols)==c?
+ mat_traits<A>::template write_element<I/mat_traits<A>::cols,I%mat_traits<A>::cols>(a) :
+ matrix_w<I+1,N>::write_element_idx(r,c,a);
+ }
+ };
+
+ template <int N>
+ struct
+ matrix_w<N,N>
+ {
+ template <class A>
+ static
+ BOOST_QVM_INLINE_TRIVIAL
+ typename mat_traits<A>::scalar_type &
+ write_element_idx( int, int, A & a )
+ {
+ BOOST_QVM_ASSERT(0);
+ return mat_traits<A>::template write_element<0,0>(a);
+ }
+ };
+ }
+
+ template <class MatType,class ScalarType,int Rows,int Cols>
+ struct
+ mat_traits_defaults
+ {
+ typedef MatType mat_type;
+ typedef ScalarType scalar_type;
+ static int const rows=Rows;
+ static int const cols=Cols;
+
+ template <int Row,int Col>
+ static
+ BOOST_QVM_INLINE_CRITICAL
+ scalar_type
+ read_element( mat_type const & x )
+ {
+ return mat_traits<mat_type>::template write_element<Row,Col>(const_cast<mat_type &>(x));
+ }
+
+ static
+ BOOST_QVM_INLINE_CRITICAL
+ scalar_type
+ read_element_idx( int r, int c, mat_type const & x )
+ {
+ return mat_traits<mat_type>::write_element_idx(r,c,const_cast<mat_type &>(x));
+ }
+
+ protected:
+
+ static
+ BOOST_QVM_INLINE_TRIVIAL
+ scalar_type &
+ write_element_idx( int r, int c, mat_type & m )
+ {
+ return qvm_detail::matrix_w<0,mat_traits<mat_type>::rows*mat_traits<mat_type>::cols>::write_element_idx(r,c,m);
+ }
+ };
+ }
+ }
+
+#endif
diff --git a/boost/qvm/quat_traits_defaults.hpp b/boost/qvm/quat_traits_defaults.hpp
new file mode 100644
index 0000000000..a343b2a3ad
--- /dev/null
+++ b/boost/qvm/quat_traits_defaults.hpp
@@ -0,0 +1,40 @@
+//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_0595DEC2C72D11E6B6B77C2A07624D53
+#define UUID_0595DEC2C72D11E6B6B77C2A07624D53
+
+#include <boost/qvm/inline.hpp>
+#include <boost/qvm/assert.hpp>
+
+namespace
+boost
+ {
+ namespace
+ qvm
+ {
+ template <class>
+ struct quat_traits;
+
+ template <class QuatType,class ScalarType>
+ struct
+ quat_traits_defaults
+ {
+ typedef QuatType quat_type;
+ typedef ScalarType scalar_type;
+
+ template <int I>
+ static
+ BOOST_QVM_INLINE_CRITICAL
+ scalar_type
+ read_element( quat_type const & x )
+ {
+ return quat_traits<quat_type>::template write_element<I>(const_cast<quat_type &>(x));
+ }
+ };
+ }
+ }
+
+#endif
diff --git a/boost/qvm/scalar_traits.hpp b/boost/qvm/scalar_traits.hpp
index 8f8107d76b..8552dfa0ab 100644
--- a/boost/qvm/scalar_traits.hpp
+++ b/boost/qvm/scalar_traits.hpp
@@ -47,6 +47,7 @@ boost
template <> struct is_scalar<unsigned long> { static bool const value=true; };
template <> struct is_scalar<float> { static bool const value=true; };
template <> struct is_scalar<double> { static bool const value=true; };
+ template <> struct is_scalar<long double> { static bool const value=true; };
namespace
qvm_detail
diff --git a/boost/qvm/vec_index.hpp b/boost/qvm/vec_index.hpp
deleted file mode 100644
index ba37979109..0000000000
--- a/boost/qvm/vec_index.hpp
+++ /dev/null
@@ -1,145 +0,0 @@
-//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_7FF8E2E00E5411E2AB79F7FE6188709B
-#define UUID_7FF8E2E00E5411E2AB79F7FE6188709B
-
-#include <boost/qvm/vec_traits.hpp>
-#include <boost/qvm/inline.hpp>
-#include <boost/qvm/assert.hpp>
-#include <boost/qvm/enable_if.hpp>
-#include <boost/qvm/error.hpp>
-#include <boost/exception/info.hpp>
-
-namespace
-boost
- {
- namespace
- qvm
- {
- ////////////////////////////////////////////////
-
- namespace
- qvm_detail
- {
- template <int D>
- struct
- vec_index_read_defined
- {
- static bool const value=false;
- };
-
- template <int I,int N>
- struct
- vector_r
- {
- template <class A>
- static
- BOOST_QVM_INLINE_CRITICAL
- typename vec_traits<A>::scalar_type
- read_element_idx( A const & a, int i )
- {
- return I==i?
- vec_traits<A>::template read_element<I>(a) :
- vector_r<I+1,N>::read_element_idx(a,i);
- }
- };
-
- template <int N>
- struct
- vector_r<N,N>
- {
- template <class A>
- static
- BOOST_QVM_INLINE_TRIVIAL
- typename vec_traits<A>::scalar_type
- read_element_idx( A const & a, int )
- {
- BOOST_QVM_ASSERT(0);
- return vec_traits<A>::template read_element<0>(a);
- }
- };
- }
-
- template <class A>
- BOOST_QVM_INLINE_TRIVIAL
- typename boost::enable_if_c<
- is_vec<A>::value &&
- !qvm_detail::vec_index_read_defined<vec_traits<A>::dim>::value,
- typename vec_traits<A>::scalar_type>::type
- vec_index_read( A const & a, int i )
- {
- return qvm_detail::vector_r<0,vec_traits<A>::dim>::read_element_idx(a,i);
- }
-
- ////////////////////////////////////////////////
-
- namespace
- qvm_detail
- {
- template <int D>
- struct
- vec_index_write_defined
- {
- static bool const value=false;
- };
-
- template <int I,int N>
- struct
- vector_w
- {
- template <class A>
- static
- BOOST_QVM_INLINE_CRITICAL
- typename vec_traits<A>::scalar_type &
- write_element_idx( A & a, int i )
- {
- return I==i?
- vec_traits<A>::template write_element<I>(a) :
- vector_w<I+1,N>::write_element_idx(a,i);
- }
- };
-
- template <int N>
- struct
- vector_w<N,N>
- {
- template <class A>
- static
- BOOST_QVM_INLINE_TRIVIAL
- typename vec_traits<A>::scalar_type &
- write_element_idx( A & a, int )
- {
- BOOST_QVM_ASSERT(0);
- return vec_traits<A>::template write_element<0>(a);
- }
- };
- }
-
- template <class A>
- BOOST_QVM_INLINE_TRIVIAL
- typename boost::enable_if_c<
- is_vec<A>::value &&
- !qvm_detail::vec_index_write_defined<vec_traits<A>::dim>::value,
- typename vec_traits<A>::scalar_type &>::type
- vec_index_write( A & a, int i )
- {
- return qvm_detail::vector_w<0,vec_traits<A>::dim>::write_element_idx(a,i);
- }
-
- ////////////////////////////////////////////////
-
- namespace
- sfinae
- {
- using ::boost::qvm::vec_index_read;
- using ::boost::qvm::vec_index_write;
- }
-
- ////////////////////////////////////////////////
- }
- }
-
-#endif
diff --git a/boost/qvm/vec_operations.hpp b/boost/qvm/vec_operations.hpp
index 7f259ac3c4..5d42df9842 100644
--- a/boost/qvm/vec_operations.hpp
+++ b/boost/qvm/vec_operations.hpp
@@ -255,7 +255,7 @@ boost
static
BOOST_QVM_INLINE_CRITICAL
scalar_type
- read_element( this_vector const & x )
+ read_element( this_vector const & )
{
BOOST_QVM_STATIC_ASSERT(I>=0);
BOOST_QVM_STATIC_ASSERT(I<Dim);
@@ -265,7 +265,7 @@ boost
static
BOOST_QVM_INLINE_CRITICAL
scalar_type
- read_element_idx( int i, this_vector const & x )
+ read_element_idx( int i, this_vector const & )
{
BOOST_QVM_ASSERT(i>=0);
BOOST_QVM_ASSERT(i<Dim);
@@ -699,6 +699,34 @@ boost
{
template <int D>
struct
+ mul_sv_defined
+ {
+ static bool const value=false;
+ };
+ }
+
+ template <class A,class B>
+ BOOST_QVM_INLINE_OPERATIONS
+ typename lazy_enable_if_c<
+ is_scalar<A>::value && is_vec<B>::value &&
+ !qvm_detail::mul_sv_defined<vec_traits<B>::dim>::value,
+ deduce_vec<B> >::type
+ operator*( A a, B const & b )
+ {
+ typedef typename deduce_vec<B>::type R;
+ R r;
+ for( int i=0; i!=vec_traits<B>::dim; ++i )
+ vec_traits<R>::write_element_idx(i,r)=a*vec_traits<B>::read_element_idx(i,b);
+ return r;
+ }
+
+ ////////////////////////////////////////////////
+
+ namespace
+ qvm_detail
+ {
+ template <int D>
+ struct
neq_vv_defined
{
static bool const value=false;
diff --git a/boost/qvm/vec_traits_defaults.hpp b/boost/qvm/vec_traits_defaults.hpp
new file mode 100644
index 0000000000..80b5f858d0
--- /dev/null
+++ b/boost/qvm/vec_traits_defaults.hpp
@@ -0,0 +1,94 @@
+//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_DFFD61ACC72311E6955FFF1F07624D53
+#define UUID_DFFD61ACC72311E6955FFF1F07624D53
+
+#include <boost/qvm/inline.hpp>
+#include <boost/qvm/assert.hpp>
+
+namespace
+boost
+ {
+ namespace
+ qvm
+ {
+ template <class>
+ struct vec_traits;
+
+ namespace
+ qvm_detail
+ {
+ template <int I,int N>
+ struct
+ vector_w
+ {
+ template <class A>
+ static
+ BOOST_QVM_INLINE_CRITICAL
+ typename vec_traits<A>::scalar_type &
+ write_element_idx( int i, A & a )
+ {
+ return I==i?
+ vec_traits<A>::template write_element<I>(a) :
+ vector_w<I+1,N>::write_element_idx(i,a);
+ }
+ };
+
+ template <int N>
+ struct
+ vector_w<N,N>
+ {
+ template <class A>
+ static
+ BOOST_QVM_INLINE_TRIVIAL
+ typename vec_traits<A>::scalar_type &
+ write_element_idx( int, A & a )
+ {
+ BOOST_QVM_ASSERT(0);
+ return vec_traits<A>::template write_element<0>(a);
+ }
+ };
+ }
+
+ template <class VecType,class ScalarType,int Dim>
+ struct
+ vec_traits_defaults
+ {
+ typedef VecType vec_type;
+ typedef ScalarType scalar_type;
+ static int const dim=Dim;
+
+ template <int I>
+ static
+ BOOST_QVM_INLINE_CRITICAL
+ scalar_type
+ read_element( vec_type const & x )
+ {
+ return vec_traits<vec_type>::template write_element<I>(const_cast<vec_type &>(x));
+ }
+
+ static
+ BOOST_QVM_INLINE_CRITICAL
+ scalar_type
+ read_element_idx( int i, vec_type const & x )
+ {
+ return vec_traits<vec_type>::write_element_idx(i,const_cast<vec_type &>(x));
+ }
+
+ protected:
+
+ static
+ BOOST_QVM_INLINE_TRIVIAL
+ scalar_type &
+ write_element_idx( int i, vec_type & m )
+ {
+ return qvm_detail::vector_w<0,vec_traits<vec_type>::dim>::write_element_idx(i,m);
+ }
+ };
+ }
+ }
+
+#endif
diff --git a/boost/random/detail/int_float_pair.hpp b/boost/random/detail/int_float_pair.hpp
new file mode 100644
index 0000000000..de253a0ecb
--- /dev/null
+++ b/boost/random/detail/int_float_pair.hpp
@@ -0,0 +1,121 @@
+/* boost random/detail/int_float_pair.hpp header file
+ *
+ * Copyright Jens Maurer 2000-2001
+ * Copyright Steven Watanabe 2010-2011
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org for most recent version including documentation.
+ *
+ * $Id$
+ *
+ */
+
+#ifndef BOOST_RANDOM_DETAIL_INT_FLOAT_PAIR_HPP
+#define BOOST_RANDOM_DETAIL_INT_FLOAT_PAIR_HPP
+
+#include <utility>
+#include <boost/integer.hpp>
+#include <boost/integer/integer_mask.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/random/uniform_01.hpp>
+#include <boost/random/uniform_int_distribution.hpp>
+#include <boost/random/detail/signed_unsigned_tools.hpp>
+#include <boost/random/detail/integer_log2.hpp>
+#include <boost/mpl/bool.hpp>
+
+namespace boost {
+namespace random {
+namespace detail {
+
+template<class Engine>
+inline typename boost::make_unsigned<typename Engine::result_type>::type
+generate_one_digit(Engine& eng, std::size_t bits)
+{
+ typedef typename Engine::result_type base_result;
+ typedef typename boost::make_unsigned<base_result>::type base_unsigned;
+
+ base_unsigned range =
+ detail::subtract<base_result>()((eng.max)(), (eng.min)());
+ base_unsigned y0_mask = (base_unsigned(2) << (bits - 1)) - 1;
+ base_unsigned y0 = (range + 1) & ~y0_mask;
+ base_unsigned u;
+ do {
+ u = detail::subtract<base_result>()(eng(), (eng.min)());
+ } while(y0 != 0 && u > base_unsigned(y0 - 1));
+ return u & y0_mask;
+}
+
+template<class RealType, std::size_t w, class Engine>
+std::pair<RealType, int> generate_int_float_pair(Engine& eng, boost::mpl::true_)
+{
+ typedef typename Engine::result_type base_result;
+ typedef typename boost::make_unsigned<base_result>::type base_unsigned;
+
+ base_unsigned range =
+ detail::subtract<base_result>()((eng.max)(), (eng.min)());
+
+ std::size_t m =
+ (range == (std::numeric_limits<base_unsigned>::max)()) ?
+ std::numeric_limits<base_unsigned>::digits :
+ detail::integer_log2(range + 1);
+
+ int bucket = 0;
+ // process as many full digits as possible into the int part
+ for(std::size_t i = 0; i < w/m; ++i) {
+ base_unsigned u = generate_one_digit(eng, m);
+ bucket = (bucket << m) | u;
+ }
+ RealType r;
+
+ const std::size_t digits = std::numeric_limits<RealType>::digits;
+ {
+ base_unsigned u = generate_one_digit(eng, m);
+ base_unsigned mask = (base_unsigned(1) << (w%m)) - 1;
+ bucket = (bucket << (w%m)) | (mask & u);
+ const RealType mult = RealType(1)/RealType(base_unsigned(1) << (m - w%m));
+ // zero out unused bits
+ if (m - w%m > digits) {
+ u &= ~(base_unsigned(1) << (m - digits));
+ }
+ r = RealType(u >> (w%m)) * mult;
+ }
+ for(std::size_t i = m - w%m; i + m < digits; ++i) {
+ base_unsigned u = generate_one_digit(eng, m);
+ r += u;
+ r *= RealType(0.5)/RealType(base_unsigned(1) << (m - 1));
+ }
+ if (m - w%m < digits)
+ {
+ const std::size_t remaining = (digits - m + w%m) % m;
+ base_unsigned u = generate_one_digit(eng, m);
+ r += u & ((base_unsigned(2) << (remaining - 1)) - 1);
+ const RealType mult = RealType(0.5)/RealType(base_unsigned(1) << (remaining - 1));
+ r *= mult;
+ }
+ return std::make_pair(r, bucket);
+}
+
+template<class RealType, std::size_t w, class Engine>
+inline std::pair<RealType, int> generate_int_float_pair(Engine& eng, boost::mpl::false_)
+{
+ int bucket = uniform_int_distribution<>(0, (1 << w) - 1)(eng);
+ RealType r = uniform_01<RealType>()(eng);
+ return std::make_pair(r, bucket);
+}
+
+template<class RealType, std::size_t w, class Engine>
+inline std::pair<RealType, int> generate_int_float_pair(Engine& eng)
+{
+ typedef typename Engine::result_type base_result;
+ return generate_int_float_pair<RealType, w>(eng,
+ boost::is_integral<base_result>());
+}
+
+} // namespace detail
+} // namespace random
+} // namespace boost
+
+#endif // BOOST_RANDOM_DETAIL_INT_FLOAT_PAIR_HPP
diff --git a/boost/random/exponential_distribution.hpp b/boost/random/exponential_distribution.hpp
index 53eaa93865..b4b95c5472 100644
--- a/boost/random/exponential_distribution.hpp
+++ b/boost/random/exponential_distribution.hpp
@@ -2,6 +2,7 @@
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 2011
+ * Copyright Jason Rhinelander 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)
@@ -23,16 +24,220 @@
#include <boost/limits.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
+#include <boost/random/detail/int_float_pair.hpp>
#include <boost/random/uniform_01.hpp>
namespace boost {
namespace random {
+namespace detail {
+
+// tables for the ziggurat algorithm
+template<class RealType>
+struct exponential_table {
+ static const RealType table_x[257];
+ static const RealType table_y[257];
+};
+
+template<class RealType>
+const RealType exponential_table<RealType>::table_x[257] = {
+ 8.6971174701310497140, 7.6971174701310497140, 6.9410336293772123602, 6.4783784938325698538,
+ 6.1441646657724730491, 5.8821443157953997963, 5.6664101674540337371, 5.4828906275260628694,
+ 5.3230905057543986131, 5.1814872813015010392, 5.0542884899813047117, 4.9387770859012514838,
+ 4.8329397410251125881, 4.7352429966017412526, 4.6444918854200854873, 4.5597370617073515513,
+ 4.4802117465284221949, 4.4052876934735729805, 4.3344436803172730116, 4.2672424802773661873,
+ 4.2033137137351843802, 4.1423408656640511251, 4.0840513104082974638, 4.0282085446479365106,
+ 3.9746060666737884793, 3.9230625001354895926, 3.8734176703995089983, 3.8255294185223367372,
+ 3.7792709924116678992, 3.7345288940397975350, 3.6912010902374189454, 3.6491955157608538478,
+ 3.6084288131289096339, 3.5688252656483374051, 3.5303158891293438633, 3.4928376547740601814,
+ 3.4563328211327607625, 3.4207483572511205323, 3.3860354424603017887, 3.3521490309001100106,
+ 3.3190474709707487166, 3.2866921715990692095, 3.2550473085704501813, 3.2240795652862645207,
+ 3.1937579032122407483, 3.1640533580259734580, 3.1349388580844407393, 3.1063890623398246660,
+ 3.0783802152540905188, 3.0508900166154554479, 3.0238975044556767713, 2.9973829495161306949,
+ 2.9713277599210896472, 2.9457143948950456386, 2.9205262865127406647, 2.8957477686001416838,
+ 2.8713640120155362592, 2.8473609656351888266, 2.8237253024500354905, 2.8004443702507381944,
+ 2.7775061464397572041, 2.7548991965623453650, 2.7326126361947007411, 2.7106360958679293686,
+ 2.6889596887418041593, 2.6675739807732670816, 2.6464699631518093905, 2.6256390267977886123,
+ 2.6050729387408355373, 2.5847638202141406911, 2.5647041263169053687, 2.5448866271118700928,
+ 2.5253043900378279427, 2.5059507635285939648, 2.4868193617402096807, 2.4679040502973649846,
+ 2.4491989329782498908, 2.4306983392644199088, 2.4123968126888708336, 2.3942890999214583288,
+ 2.3763701405361408194, 2.3586350574093374601, 2.3410791477030346875, 2.3236978743901964559,
+ 2.3064868582835798692, 2.2894418705322694265, 2.2725588255531546952, 2.2558337743672190441,
+ 2.2392628983129087111, 2.2228425031110364013, 2.2065690132576635755, 2.1904389667232199235,
+ 2.1744490099377744673, 2.1585958930438856781, 2.1428764653998416425, 2.1272876713173679737,
+ 2.1118265460190418108, 2.0964902118017147637, 2.0812758743932248696, 2.0661808194905755036,
+ 2.0512024094685848641, 2.0363380802487695916, 2.0215853383189260770, 2.0069417578945183144,
+ 1.9924049782135764992, 1.9779727009573602295, 1.9636426877895480401, 1.9494127580071845659,
+ 1.9352807862970511135, 1.9212447005915276767, 1.9073024800183871196, 1.8934521529393077332,
+ 1.8796917950722108462, 1.8660195276928275962, 1.8524335159111751661, 1.8389319670188793980,
+ 1.8255131289035192212, 1.8121752885263901413, 1.7989167704602903934, 1.7857359354841254047,
+ 1.7726311792313049959, 1.7596009308890742369, 1.7466436519460739352, 1.7337578349855711926,
+ 1.7209420025219350428, 1.7081947058780575683, 1.6955145241015377061, 1.6829000629175537544,
+ 1.6703499537164519163, 1.6578628525741725325, 1.6454374393037234057, 1.6330724165359912048,
+ 1.6207665088282577216, 1.6085184617988580769, 1.5963270412864831349, 1.5841910325326886695,
+ 1.5721092393862294810, 1.5600804835278879161, 1.5481036037145133070, 1.5361774550410318943,
+ 1.5243009082192260050, 1.5124728488721167573, 1.5006921768428164936, 1.4889578055167456003,
+ 1.4772686611561334579, 1.4656236822457450411, 1.4540218188487932264, 1.4424620319720121876,
+ 1.4309432929388794104, 1.4194645827699828254, 1.4080248915695353509, 1.3966232179170417110,
+ 1.3852585682631217189, 1.3739299563284902176, 1.3626364025050864742, 1.3513769332583349176,
+ 1.3401505805295045843, 1.3289563811371163220, 1.3177933761763245480, 1.3066606104151739482,
+ 1.2955571316866007210, 1.2844819902750125450, 1.2734342382962410994, 1.2624129290696153434,
+ 1.2514171164808525098, 1.2404458543344064544, 1.2294981956938491599, 1.2185731922087903071,
+ 1.2076698934267612830, 1.1967873460884031665, 1.1859245934042023557, 1.1750806743109117687,
+ 1.1642546227056790397, 1.1534454666557748056, 1.1426522275816728928, 1.1318739194110786733,
+ 1.1211095477013306083, 1.1103581087274114281, 1.0996185885325976575, 1.0888899619385472598,
+ 1.0781711915113727024, 1.0674612264799681530, 1.0567590016025518414, 1.0460634359770445503,
+ 1.0353734317905289496, 1.0246878730026178052, 1.0140056239570971074, 1.0033255279156973717,
+ 0.99264640550727647009, 0.98196705308506317914, 0.97128624098390397896, 0.96060271166866709917,
+ 0.94991517776407659940, 0.93922231995526297952, 0.92852278474721113999, 0.91781518207004493915,
+ 0.90709808271569100600, 0.89637001558989069006, 0.88562946476175228052, 0.87487486629102585352,
+ 0.86410460481100519511, 0.85331700984237406386, 0.84251035181036928333, 0.83168283773427388393,
+ 0.82083260655441252290, 0.80995772405741906620, 0.79905617735548788109, 0.78812586886949324977,
+ 0.77716460975913043936, 0.76617011273543541328, 0.75513998418198289808, 0.74407171550050873971,
+ 0.73296267358436604916, 0.72181009030875689912, 0.71061105090965570413, 0.69936248110323266174,
+ 0.68806113277374858613, 0.67670356802952337911, 0.66528614139267855405, 0.65380497984766565353,
+ 0.64225596042453703448, 0.63063468493349100113, 0.61893645139487678178, 0.60715622162030085137,
+ 0.59528858429150359384, 0.58332771274877027785, 0.57126731653258903915, 0.55910058551154127652,
+ 0.54682012516331112550, 0.53441788123716615385, 0.52188505159213564105, 0.50921198244365495319,
+ 0.49638804551867159754, 0.48340149165346224782, 0.47023927508216945338, 0.45688684093142071279,
+ 0.44332786607355296305, 0.42954394022541129589, 0.41551416960035700100, 0.40121467889627836229,
+ 0.38661797794112021568, 0.37169214532991786118, 0.35639976025839443721, 0.34069648106484979674,
+ 0.32452911701691008547, 0.30783295467493287307, 0.29052795549123115167, 0.27251318547846547924,
+ 0.25365836338591284433, 0.23379048305967553619, 0.21267151063096745264, 0.18995868962243277774,
+ 0.16512762256418831796, 0.13730498094001380420, 0.10483850756582017915, 0.063852163815003480173,
+ 0
+};
+
+template<class RealType>
+const RealType exponential_table<RealType>::table_y[257] = {
+ 0, 0.00045413435384149675545, 0.00096726928232717452884, 0.0015362997803015723824,
+ 0.0021459677437189061793, 0.0027887987935740759640, 0.0034602647778369039855, 0.0041572951208337952532,
+ 0.0048776559835423925804, 0.0056196422072054831710, 0.0063819059373191794422, 0.0071633531836349841425,
+ 0.0079630774380170392396, 0.0087803149858089752347, 0.0096144136425022094101, 0.010464810181029979488,
+ 0.011331013597834597488, 0.012212592426255380661, 0.013109164931254991070, 0.014020391403181937334,
+ 0.014945968011691148079, 0.015885621839973162490, 0.016839106826039946359, 0.017806200410911360563,
+ 0.018786700744696029497, 0.019780424338009741737, 0.020787204072578117603, 0.021806887504283582125,
+ 0.022839335406385238829, 0.023884420511558170348, 0.024942026419731782971, 0.026012046645134218076,
+ 0.027094383780955798424, 0.028188948763978634421, 0.029295660224637394015, 0.030414443910466605492,
+ 0.031545232172893605499, 0.032687963508959533317, 0.033842582150874329031, 0.035009037697397411067,
+ 0.036187284781931419754, 0.037377282772959360128, 0.038578995503074859626, 0.039792391023374122670,
+ 0.041017441380414820816, 0.042254122413316231413, 0.043502413568888183301, 0.044762297732943280694,
+ 0.046033761076175166762, 0.047316792913181548703, 0.048611385573379494401, 0.049917534282706374944,
+ 0.051235237055126279830, 0.052564494593071689595, 0.053905310196046085104, 0.055257689676697038322,
+ 0.056621641283742874438, 0.057997175631200659098, 0.059384305633420264487, 0.060783046445479636051,
+ 0.062193415408540996150, 0.063615431999807331076, 0.065049117786753755036, 0.066494496385339779043,
+ 0.067951593421936607770, 0.069420436498728751675, 0.070901055162371828426, 0.072393480875708743023,
+ 0.073897746992364746308, 0.075413888734058408453, 0.076941943170480510100, 0.078481949201606426042,
+ 0.080033947542319910023, 0.081597980709237420930, 0.083174093009632380354, 0.084762330532368125386,
+ 0.086362741140756912277, 0.087975374467270219300, 0.089600281910032864534, 0.091237516631040162057,
+ 0.092887133556043546523, 0.094549189376055853718, 0.096223742550432800103, 0.097910853311492199618,
+ 0.099610583670637128826, 0.10132299742595363588, 0.10304816017125771553, 0.10478613930657016928,
+ 0.10653700405000166218, 0.10830082545103379867, 0.11007767640518539026, 0.11186763167005629731,
+ 0.11367076788274431301, 0.11548716357863353664, 0.11731689921155557057, 0.11916005717532768467,
+ 0.12101672182667483729, 0.12288697950954513498, 0.12477091858083096578, 0.12666862943751066518,
+ 0.12858020454522817870, 0.13050573846833078225, 0.13244532790138752023, 0.13439907170221363078,
+ 0.13636707092642885841, 0.13834942886358021406, 0.14034625107486244210, 0.14235764543247220043,
+ 0.14438372216063476473, 0.14642459387834493787, 0.14848037564386679222, 0.15055118500103990354,
+ 0.15263714202744286154, 0.15473836938446807312, 0.15685499236936522013, 0.15898713896931420572,
+ 0.16113493991759203183, 0.16329852875190180795, 0.16547804187493600915, 0.16767361861725019322,
+ 0.16988540130252766513, 0.17211353531532005700, 0.17435816917135348788, 0.17661945459049489581,
+ 0.17889754657247831241, 0.18119260347549629488, 0.18350478709776746150, 0.18583426276219711495,
+ 0.18818119940425430485, 0.19054576966319540013, 0.19292814997677133873, 0.19532852067956322315,
+ 0.19774706610509886464, 0.20018397469191127727, 0.20263943909370901930, 0.20511365629383770880,
+ 0.20760682772422204205, 0.21011915938898825914, 0.21265086199297827522, 0.21520215107537867786,
+ 0.21777324714870053264, 0.22036437584335949720, 0.22297576805812018050, 0.22560766011668406495,
+ 0.22826029393071670664, 0.23093391716962742173, 0.23362878343743333945, 0.23634515245705964715,
+ 0.23908329026244917002, 0.24184346939887722761, 0.24462596913189210901, 0.24743107566532763894,
+ 0.25025908236886230967, 0.25311029001562948171, 0.25598500703041538015, 0.25888354974901621678,
+ 0.26180624268936295243, 0.26475341883506220209, 0.26772541993204481808, 0.27072259679906003167,
+ 0.27374530965280298302, 0.27679392844851734458, 0.27986883323697289920, 0.28297041453878076010,
+ 0.28609907373707684673, 0.28925522348967773308, 0.29243928816189258772, 0.29565170428126120948,
+ 0.29889292101558177099, 0.30216340067569352897, 0.30546361924459023541, 0.30879406693456016794,
+ 0.31215524877417956945, 0.31554768522712893632, 0.31897191284495723773, 0.32242848495608914289,
+ 0.32591797239355619822, 0.32944096426413633091, 0.33299806876180896713, 0.33658991402867758144,
+ 0.34021714906678004560, 0.34388044470450243010, 0.34758049462163698567, 0.35131801643748334681,
+ 0.35509375286678745925, 0.35890847294874976196, 0.36276297335481777335, 0.36665807978151414890,
+ 0.37059464843514599421, 0.37457356761590215193, 0.37859575940958081092, 0.38266218149600982112,
+ 0.38677382908413768115, 0.39093173698479710717, 0.39513698183329015336, 0.39939068447523107877,
+ 0.40369401253053026739, 0.40804818315203238238, 0.41245446599716116772, 0.41691418643300289465,
+ 0.42142872899761659635, 0.42599954114303435739, 0.43062813728845883923, 0.43531610321563659758,
+ 0.44006510084235387501, 0.44487687341454851593, 0.44975325116275498919, 0.45469615747461548049,
+ 0.45970761564213768669, 0.46478975625042618067, 0.46994482528395999841, 0.47517519303737738299,
+ 0.48048336393045423016, 0.48587198734188493564, 0.49134386959403255500, 0.49690198724154955294,
+ 0.50254950184134769289, 0.50828977641064283495, 0.51412639381474855788, 0.52006317736823356823,
+ 0.52610421398361972602, 0.53225388026304326945, 0.53851687200286186590, 0.54489823767243963663,
+ 0.55140341654064131685, 0.55803828226258748140, 0.56480919291240022434, 0.57172304866482579008,
+ 0.57878735860284503057, 0.58601031847726802755, 0.59340090169173341521, 0.60096896636523224742,
+ 0.60872538207962206507, 0.61668218091520762326, 0.62485273870366592605, 0.63325199421436607968,
+ 0.64189671642726607018, 0.65080583341457104881, 0.66000084107899974178, 0.66950631673192477684,
+ 0.67935057226476538741, 0.68956649611707798890, 0.70019265508278816709, 0.71127476080507597882,
+ 0.72286765959357200702, 0.73503809243142351530, 0.74786862198519510742, 0.76146338884989624862,
+ 0.77595685204011559675, 0.79152763697249565519, 0.80842165152300838005, 0.82699329664305033399,
+ 0.84778550062398962096, 0.87170433238120363669, 0.90046992992574643800, 0.93814368086217467916,
+ 1
+};
+
+template<class RealType = double>
+struct unit_exponential_distribution
+{
+ template<class Engine>
+ RealType operator()(Engine& eng) {
+ const double * const table_x = exponential_table<double>::table_x;
+ const double * const table_y = exponential_table<double>::table_y;
+ RealType shift(0);
+ for(;;) {
+ std::pair<RealType, int> vals = generate_int_float_pair<RealType, 8>(eng);
+ int i = vals.second;
+ RealType x = vals.first * RealType(table_x[i]);
+ if(x < RealType(table_x[i + 1])) return shift + x;
+ // For i=0 we need to generate from the tail, but because this is an exponential
+ // distribution, the tail looks exactly like the body, so we can simply repeat with a
+ // shift:
+ if (i == 0) shift += RealType(table_x[1]);
+ else {
+ RealType y01 = uniform_01<RealType>()(eng);
+ RealType y = RealType(table_y[i]) + y01 * RealType(table_y[i+1] - table_y[i]);
+
+ // All we care about is whether these are < or > 0; these values are equal to
+ // (lbound) or proportional to (ubound) `y` minus the lower/upper bound.
+ RealType y_above_ubound = RealType(table_x[i] - table_x[i+1]) * y01 - (RealType(table_x[i]) - x),
+ y_above_lbound = y - (RealType(table_y[i+1]) + (RealType(table_x[i+1]) - x) * RealType(table_y[i+1]));
+
+ if (y_above_ubound < 0 // if above the upper bound reject immediately
+ &&
+ (
+ y_above_lbound < 0 // If below the lower bound accept immediately
+ ||
+ y < f(x) // Otherwise it's between the bounds and we need a full check
+ )
+ ) {
+ return x + shift;
+ }
+ }
+ }
+ }
+ static RealType f(RealType x) {
+ using std::exp;
+ return exp(-x);
+ }
+};
+
+} // namespace detail
+
+
/**
* The exponential distribution is a model of \random_distribution with
* a single parameter lambda.
*
* It has \f$\displaystyle p(x) = \lambda e^{-\lambda x}\f$
+ *
+ * The implementation uses the "ziggurat" algorithm, as described in
+ *
+ * @blockquote
+ * "The Ziggurat Method for Generating Random Variables",
+ * George Marsaglia and Wai Wan Tsang, Journal of Statistical Software
+ * Volume 5, Number 8 (2000), 1-7.
+ * @endblockquote
*/
template<class RealType = double>
class exponential_distribution
@@ -127,9 +332,8 @@ public:
template<class Engine>
result_type operator()(Engine& eng) const
{
- using std::log;
- return -result_type(1) /
- _lambda * log(result_type(1)-uniform_01<RealType>()(eng));
+ detail::unit_exponential_distribution<RealType> impl;
+ return impl(eng) / _lambda;
}
/**
diff --git a/boost/random/normal_distribution.hpp b/boost/random/normal_distribution.hpp
index 6fffc4aef5..b7ff3eba9b 100644
--- a/boost/random/normal_distribution.hpp
+++ b/boost/random/normal_distribution.hpp
@@ -23,17 +23,11 @@
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <boost/static_assert.hpp>
-#include <boost/integer.hpp>
-#include <boost/integer/integer_mask.hpp>
-#include <boost/type_traits/is_integral.hpp>
-#include <boost/type_traits/make_unsigned.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
-#include <boost/random/detail/integer_log2.hpp>
+#include <boost/random/detail/int_float_pair.hpp>
#include <boost/random/uniform_01.hpp>
-#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/exponential_distribution.hpp>
-#include <boost/mpl/bool.hpp>
namespace boost {
namespace random {
@@ -121,89 +115,6 @@ const RealType normal_table<RealType>::table_y[129] = {
1
};
-template<class Engine>
-inline typename boost::make_unsigned<typename Engine::result_type>::type
-generate_one_digit(Engine& eng, std::size_t bits)
-{
- typedef typename Engine::result_type base_result;
- typedef typename boost::make_unsigned<base_result>::type base_unsigned;
-
- base_unsigned range =
- detail::subtract<base_result>()((eng.max)(), (eng.min)());
- base_unsigned y0_mask = (base_unsigned(2) << (bits - 1)) - 1;
- base_unsigned y0 = (range + 1) & ~y0_mask;
- base_unsigned u;
- do {
- u = detail::subtract<base_result>()(eng(), (eng.min)());
- } while(y0 != 0 && u > base_unsigned(y0 - 1));
- return u & y0_mask;
-}
-
-template<class RealType, std::size_t w, class Engine>
-std::pair<RealType, int> generate_int_float_pair(Engine& eng, boost::mpl::true_)
-{
- typedef typename Engine::result_type base_result;
- typedef typename boost::make_unsigned<base_result>::type base_unsigned;
-
- base_unsigned range =
- detail::subtract<base_result>()((eng.max)(), (eng.min)());
-
- std::size_t m =
- (range == (std::numeric_limits<base_unsigned>::max)()) ?
- std::numeric_limits<base_unsigned>::digits :
- detail::integer_log2(range + 1);
-
- int bucket = 0;
- // process as many full digits as possible into the int part
- for(std::size_t i = 0; i < w/m; ++i) {
- base_unsigned u = generate_one_digit(eng, m);
- bucket = (bucket << m) | u;
- }
- RealType r;
-
- const std::size_t digits = std::numeric_limits<RealType>::digits;
- {
- base_unsigned u = generate_one_digit(eng, m);
- base_unsigned mask = (base_unsigned(1) << (w%m)) - 1;
- bucket = (bucket << (w%m)) | (mask & u);
- const RealType mult = RealType(1)/RealType(base_unsigned(1) << (m - w%m));
- // zero out unused bits
- if (m - w%m > digits) {
- u &= ~(base_unsigned(1) << (m - digits));
- }
- r = RealType(u >> (w%m)) * mult;
- }
- for(std::size_t i = m - w%m; i + m < digits; ++i) {
- base_unsigned u = generate_one_digit(eng, m);
- r += u;
- r *= RealType(0.5)/RealType(base_unsigned(1) << (m - 1));
- }
- if (m - w%m < digits)
- {
- const std::size_t remaining = (digits - m + w%m) % m;
- base_unsigned u = generate_one_digit(eng, m);
- r += u & ((base_unsigned(2) << (remaining - 1)) - 1);
- const RealType mult = RealType(0.5)/RealType(base_unsigned(1) << (remaining - 1));
- r *= mult;
- }
- return std::make_pair(r, bucket);
-}
-
-template<class RealType, std::size_t w, class Engine>
-inline std::pair<RealType, int> generate_int_float_pair(Engine& eng, boost::mpl::false_)
-{
- int bucket = uniform_int_distribution<>(0, (1 << w) - 1)(eng);
- RealType r = uniform_01<RealType>()(eng);
- return std::make_pair(r, bucket);
-}
-
-template<class RealType, std::size_t w, class Engine>
-inline std::pair<RealType, int> generate_int_float_pair(Engine& eng)
-{
- typedef typename Engine::result_type base_result;
- return generate_int_float_pair<RealType, w>(eng,
- boost::is_integral<base_result>());
-}
template<class RealType = double>
struct unit_normal_distribution
@@ -220,29 +131,77 @@ struct unit_normal_distribution
RealType x = vals.first * RealType(table_x[i]);
if(x < table_x[i + 1]) return x * sign;
if(i == 0) return generate_tail(eng) * sign;
- RealType y = RealType(table_y[i]) + uniform_01<RealType>()(eng) * RealType(table_y[i + 1] - table_y[i]);
- if (y < f(x)) return x * sign;
+
+ RealType y01 = uniform_01<RealType>()(eng);
+ RealType y = RealType(table_y[i]) + y01 * RealType(table_y[i + 1] - table_y[i]);
+
+ // These store the value y - bound, or something proportional to that difference:
+ RealType y_above_ubound, y_above_lbound;
+
+ // There are three cases to consider:
+ // - convex regions (where x[i] > x[j] >= 1)
+ // - concave regions (where 1 <= x[i] < x[j])
+ // - region containing the inflection point (where x[i] > 1 > x[j])
+ // For convex (concave), exp^(-x^2/2) is bounded below (above) by the tangent at
+ // (x[i],y[i]) and is bounded above (below) by the diagonal line from (x[i+1],y[i+1]) to
+ // (x[i],y[i]).
+ //
+ // *If* the inflection point region satisfies slope(x[i+1]) < slope(diagonal), then we
+ // can treat the inflection region as a convex region: this condition is necessary and
+ // sufficient to ensure that the curve lies entirely below the diagonal (that, in turn,
+ // also implies that it will be above the tangent at x[i]).
+ //
+ // For the current table size (128), this is satisfied: slope(x[i+1]) = -0.60653 <
+ // slope(diag) = -0.60649, and so we have only two cases below instead of three.
+
+ if (table_x[i] >= 1) { // convex (incl. inflection)
+ y_above_ubound = RealType(table_x[i] - table_x[i+1]) * y01 - (RealType(table_x[i]) - x);
+ y_above_lbound = y - (RealType(table_y[i]) + (RealType(table_x[i]) - x) * RealType(table_y[i]) * RealType(table_x[i]));
+ }
+ else { // concave
+ y_above_lbound = RealType(table_x[i] - table_x[i+1]) * y01 - (RealType(table_x[i]) - x);
+ y_above_ubound = y - (RealType(table_y[i]) + (RealType(table_x[i]) - x) * RealType(table_y[i]) * RealType(table_x[i]));
+ }
+
+ if (y_above_ubound < 0 // if above the upper bound reject immediately
+ &&
+ (
+ y_above_lbound < 0 // If below the lower bound accept immediately
+ ||
+ y < f(x) // Otherwise it's between the bounds and we need a full check
+ )
+ ) {
+ return x * sign;
+ }
}
}
static RealType f(RealType x) {
using std::exp;
- return exp(-x*x/2);
+ return exp(-(x*x/2));
}
+ // Generate from the tail using rejection sampling from the exponential(x_1) distribution,
+ // shifted by x_1. This looks a little different from the usual rejection sampling because it
+ // transforms the condition by taking the log of both sides, thus avoiding the costly exp() call
+ // on the RHS, then takes advantage of the fact that -log(unif01) is simply generating an
+ // exponential (by inverse cdf sampling) by replacing the log(unif01) on the LHS with a
+ // exponential(1) draw, y.
template<class Engine>
RealType generate_tail(Engine& eng) {
- boost::random::exponential_distribution<RealType> exponential;
const RealType tail_start = RealType(normal_table<double>::table_x[1]);
+ boost::random::exponential_distribution<RealType> exp_x(tail_start);
+ boost::random::exponential_distribution<RealType> exp_y;
for(;;) {
- RealType x = exponential(eng)/tail_start;
- RealType y = exponential(eng);
+ RealType x = exp_x(eng);
+ RealType y = exp_y(eng);
+ // If we were doing non-transformed rejection sampling, this condition would be:
+ // if (unif01 < exp(-.5*x*x)) return x + tail_start;
if(2*y > x*x) return x + tail_start;
}
}
};
-}
+} // namespace detail
-// deterministic Box-Muller method, uses trigonometric functions
/**
* Instantiations of class template normal_distribution model a
@@ -252,6 +211,14 @@ struct unit_normal_distribution
* \frac{1}{\sqrt{2\pi}\sigma} e^{-\frac{(x-\mu)^2}{2\sigma^2}}
* \f$,
* where mean and sigma are the parameters of the distribution.
+ *
+ * The implementation uses the "ziggurat" algorithm, as described in
+ *
+ * @blockquote
+ * "The Ziggurat Method for Generating Random Variables",
+ * George Marsaglia and Wai Wan Tsang, Journal of Statistical Software,
+ * Volume 5, Number 8 (2000), 1-7.
+ * @endblockquote
*/
template<class RealType = double>
class normal_distribution
diff --git a/boost/rational.hpp b/boost/rational.hpp
index 2b74b05fd3..4fc06c9edc 100644
--- a/boost/rational.hpp
+++ b/boost/rational.hpp
@@ -32,7 +32,7 @@
// 05 May 12 Reduced use of implicit gcd (Mario Lang)
// 05 Nov 06 Change rational_cast to not depend on division between different
// types (Daryle Walker)
-// 04 Nov 06 Off-load GCD and LCM to Boost.Math; add some invariant checks;
+// 04 Nov 06 Off-load GCD and LCM to Boost.Integer; add some invariant checks;
// add std::numeric_limits<> requirement to help GCD (Daryle Walker)
// 31 Oct 06 Recoded both operator< to use round-to-negative-infinity
// divisions; the rational-value version now uses continued fraction
@@ -83,6 +83,10 @@
#include <limits> // for std::numeric_limits
#include <boost/static_assert.hpp> // for BOOST_STATIC_ASSERT
#include <boost/throw_exception.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_class.hpp>
+#include <boost/type_traits/is_same.hpp>
// Control whether depreciated GCD and LCM functions are included (default: yes)
#ifndef BOOST_CONTROL_RATIONAL_HAS_GCD
@@ -95,18 +99,34 @@ namespace boost {
template <typename IntType>
IntType gcd(IntType n, IntType m)
{
- // Defer to the version in Boost.Math
+ // Defer to the version in Boost.Integer
return integer::gcd( n, m );
}
template <typename IntType>
IntType lcm(IntType n, IntType m)
{
- // Defer to the version in Boost.Math
+ // Defer to the version in Boost.Integer
return integer::lcm( n, m );
}
#endif // BOOST_CONTROL_RATIONAL_HAS_GCD
+namespace rational_detail{
+
+ template <class FromInt, class ToInt>
+ struct is_compatible_integer
+ {
+ BOOST_STATIC_CONSTANT(bool, value = ((std::numeric_limits<FromInt>::is_specialized && std::numeric_limits<FromInt>::is_integer
+ && (std::numeric_limits<FromInt>::digits <= std::numeric_limits<ToInt>::digits)
+ && (std::numeric_limits<FromInt>::radix == std::numeric_limits<ToInt>::radix)
+ && ((std::numeric_limits<FromInt>::is_signed == false) || (std::numeric_limits<ToInt>::is_signed == true))
+ && is_convertible<FromInt, ToInt>::value)
+ || is_same<FromInt, ToInt>::value)
+ || (is_class<ToInt>::value && is_class<FromInt>::value && is_convertible<FromInt, ToInt>::value));
+ };
+
+}
+
class bad_rational : public std::domain_error
{
public:
@@ -115,24 +135,7 @@ public:
};
template <typename IntType>
-class rational :
- less_than_comparable < rational<IntType>,
- equality_comparable < rational<IntType>,
- less_than_comparable2 < rational<IntType>, IntType,
- equality_comparable2 < rational<IntType>, IntType,
- addable < rational<IntType>,
- subtractable < rational<IntType>,
- multipliable < rational<IntType>,
- dividable < rational<IntType>,
- addable2 < rational<IntType>, IntType,
- subtractable2 < rational<IntType>, IntType,
- subtractable2_left < rational<IntType>, IntType,
- multipliable2 < rational<IntType>, IntType,
- dividable2 < rational<IntType>, IntType,
- dividable2_left < rational<IntType>, IntType,
- incrementable < rational<IntType>,
- decrementable < rational<IntType>
- > > > > > > > > > > > > > > > >
+class rational
{
// Class-wide pre-conditions
BOOST_STATIC_ASSERT( ::std::numeric_limits<IntType>::is_specialized );
@@ -149,26 +152,104 @@ public:
BOOST_CONSTEXPR
rational() : num(0), den(1) {}
- BOOST_CONSTEXPR
- rational(param_type n) : num(n), den(1) {}
- rational(param_type n, param_type d) : num(n), den(d) { normalize(); }
+ template <class T>
+ BOOST_CONSTEXPR rational(const T& n, typename enable_if_c<
+ rational_detail::is_compatible_integer<T, IntType>::value
+ >::type const* = 0) : num(n), den(1) {}
+ template <class T, class U>
+ rational(const T& n, const U& d, typename enable_if_c<
+ rational_detail::is_compatible_integer<T, IntType>::value && rational_detail::is_compatible_integer<U, IntType>::value
+ >::type const* = 0) : num(n), den(d) {
+ normalize();
+ }
-#ifndef BOOST_NO_MEMBER_TEMPLATES
template < typename NewType >
BOOST_CONSTEXPR explicit
- rational(rational<NewType> const &r)
+ rational(rational<NewType> const &r, typename enable_if_c<rational_detail::is_compatible_integer<NewType, IntType>::value>::type const* = 0)
: num(r.numerator()), den(is_normalized(int_type(r.numerator()),
int_type(r.denominator())) ? r.denominator() :
(BOOST_THROW_EXCEPTION(bad_rational("bad rational: denormalized conversion")), 0)){}
-#endif
+ template < typename NewType >
+ BOOST_CONSTEXPR explicit
+ rational(rational<NewType> const &r, typename disable_if_c<rational_detail::is_compatible_integer<NewType, IntType>::value>::type const* = 0)
+ : num(r.numerator()), den(is_normalized(int_type(r.numerator()),
+ int_type(r.denominator())) && is_safe_narrowing_conversion(r.denominator()) && is_safe_narrowing_conversion(r.numerator()) ? r.denominator() :
+ (BOOST_THROW_EXCEPTION(bad_rational("bad rational: denormalized conversion")), 0)){}
// Default copy constructor and assignment are fine
// Add assignment from IntType
- rational& operator=(param_type i) { num = i; den = 1; return *this; }
+ template <class T>
+ typename enable_if_c<
+ rational_detail::is_compatible_integer<T, IntType>::value, rational &
+ >::type operator=(const T& n) { return assign(static_cast<IntType>(n), static_cast<IntType>(1)); }
// Assign in place
- rational& assign(param_type n, param_type d);
+ template <class T, class U>
+ typename enable_if_c<
+ rational_detail::is_compatible_integer<T, IntType>::value && rational_detail::is_compatible_integer<U, IntType>::value, rational &
+ >::type assign(const T& n, const U& d)
+ {
+ return *this = rational<IntType>(static_cast<IntType>(n), static_cast<IntType>(d));
+ }
+ //
+ // The following overloads should probably *not* be provided -
+ // but are provided for backwards compatibity reasons only.
+ // These allow for construction/assignment from types that
+ // are wider than IntType only if there is an implicit
+ // conversion from T to IntType, they will throw a bad_rational
+ // if the conversion results in loss of precision or undefined behaviour.
+ //
+ template <class T>
+ rational(const T& n, typename enable_if_c<
+ std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer
+ && !rational_detail::is_compatible_integer<T, IntType>::value
+ && (std::numeric_limits<T>::radix == std::numeric_limits<IntType>::radix)
+ && is_convertible<T, IntType>::value
+ >::type const* = 0)
+ {
+ assign(n, static_cast<T>(1));
+ }
+ template <class T, class U>
+ rational(const T& n, const U& d, typename enable_if_c<
+ (!rational_detail::is_compatible_integer<T, IntType>::value
+ || !rational_detail::is_compatible_integer<U, IntType>::value)
+ && std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer
+ && (std::numeric_limits<T>::radix == std::numeric_limits<IntType>::radix)
+ && is_convertible<T, IntType>::value &&
+ std::numeric_limits<U>::is_specialized && std::numeric_limits<U>::is_integer
+ && (std::numeric_limits<U>::radix == std::numeric_limits<IntType>::radix)
+ && is_convertible<U, IntType>::value
+ >::type const* = 0)
+ {
+ assign(n, d);
+ }
+ template <class T>
+ typename enable_if_c<
+ std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer
+ && !rational_detail::is_compatible_integer<T, IntType>::value
+ && (std::numeric_limits<T>::radix == std::numeric_limits<IntType>::radix)
+ && is_convertible<T, IntType>::value,
+ rational &
+ >::type operator=(const T& n) { return assign(n, static_cast<T>(1)); }
+
+ template <class T, class U>
+ typename enable_if_c<
+ (!rational_detail::is_compatible_integer<T, IntType>::value
+ || !rational_detail::is_compatible_integer<U, IntType>::value)
+ && std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer
+ && (std::numeric_limits<T>::radix == std::numeric_limits<IntType>::radix)
+ && is_convertible<T, IntType>::value &&
+ std::numeric_limits<U>::is_specialized && std::numeric_limits<U>::is_integer
+ && (std::numeric_limits<U>::radix == std::numeric_limits<IntType>::radix)
+ && is_convertible<U, IntType>::value,
+ rational &
+ >::type assign(const T& n, const U& d)
+ {
+ if(!is_safe_narrowing_conversion(n) || !is_safe_narrowing_conversion(d))
+ BOOST_THROW_EXCEPTION(bad_rational());
+ return *this = rational<IntType>(static_cast<IntType>(n), static_cast<IntType>(d));
+ }
// Access to representation
BOOST_CONSTEXPR
@@ -182,15 +263,66 @@ public:
rational& operator*= (const rational& r);
rational& operator/= (const rational& r);
- rational& operator+= (param_type i) { num += i * den; return *this; }
- rational& operator-= (param_type i) { num -= i * den; return *this; }
- rational& operator*= (param_type i);
- rational& operator/= (param_type i);
+ template <class T>
+ typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, rational&>::type operator+= (const T& i)
+ {
+ num += i * den;
+ return *this;
+ }
+ template <class T>
+ typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, rational&>::type operator-= (const T& i)
+ {
+ num -= i * den;
+ return *this;
+ }
+ template <class T>
+ typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, rational&>::type operator*= (const T& i)
+ {
+ // Avoid overflow and preserve normalization
+ IntType gcd = integer::gcd(static_cast<IntType>(i), den);
+ num *= i / gcd;
+ den /= gcd;
+ return *this;
+ }
+ template <class T>
+ typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, rational&>::type operator/= (const T& i)
+ {
+ // Avoid repeated construction
+ IntType const zero(0);
+
+ if(i == zero) BOOST_THROW_EXCEPTION(bad_rational());
+ if(num == zero) return *this;
+
+ // Avoid overflow and preserve normalization
+ IntType const gcd = integer::gcd(num, static_cast<IntType>(i));
+ num /= gcd;
+ den *= i / gcd;
+
+ if(den < zero) {
+ num = -num;
+ den = -den;
+ }
+
+ return *this;
+ }
// Increment and decrement
const rational& operator++() { num += den; return *this; }
const rational& operator--() { num -= den; return *this; }
+ rational operator++(int)
+ {
+ rational t(*this);
+ ++(*this);
+ return t;
+ }
+ rational operator--(int)
+ {
+ rational t(*this);
+ --(*this);
+ return t;
+ }
+
// Operator not
BOOST_CONSTEXPR
bool operator!() const { return !num; }
@@ -213,13 +345,37 @@ public:
// Comparison operators
bool operator< (const rational& r) const;
+ bool operator> (const rational& r) const { return r < *this; }
BOOST_CONSTEXPR
bool operator== (const rational& r) const;
- bool operator< (param_type i) const;
- bool operator> (param_type i) const;
- BOOST_CONSTEXPR
- bool operator== (param_type i) const;
+ template <class T>
+ typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, bool>::type operator< (const T& i) const
+ {
+ // Avoid repeated construction
+ int_type const zero(0);
+
+ // Break value into mixed-fraction form, w/ always-nonnegative remainder
+ BOOST_ASSERT(this->den > zero);
+ int_type q = this->num / this->den, r = this->num % this->den;
+ while(r < zero) { r += this->den; --q; }
+
+ // Compare with just the quotient, since the remainder always bumps the
+ // value up. [Since q = floor(n/d), and if n/d < i then q < i, if n/d == i
+ // then q == i, if n/d == i + r/d then q == i, and if n/d >= i + 1 then
+ // q >= i + 1 > i; therefore n/d < i iff q < i.]
+ return q < i;
+ }
+ template <class T>
+ typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, bool>::type operator>(const T& i) const
+ {
+ return operator==(i) ? false : !operator<(i);
+ }
+ template <class T>
+ BOOST_CONSTEXPR typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, bool>::type operator== (const T& i) const
+ {
+ return ((den == IntType(1)) && (num == i));
+ }
private:
// Implementation - numerator and denominator (normalized).
@@ -251,15 +407,70 @@ private:
return d > zero && ( n != zero || d == one ) && inner_abs( inner_gcd(n,
d, zero), zero ) == one;
}
+ //
+ // Conversion checks:
+ //
+ // (1) From an unsigned type with more digits than IntType:
+ //
+ template <class T>
+ BOOST_CONSTEXPR static typename boost::enable_if_c<(std::numeric_limits<T>::digits > std::numeric_limits<IntType>::digits) && (std::numeric_limits<T>::is_signed == false), bool>::type is_safe_narrowing_conversion(const T& val)
+ {
+ return val < (T(1) << std::numeric_limits<IntType>::digits);
+ }
+ //
+ // (2) From a signed type with more digits than IntType, and IntType also signed:
+ //
+ template <class T>
+ BOOST_CONSTEXPR static typename boost::enable_if_c<(std::numeric_limits<T>::digits > std::numeric_limits<IntType>::digits) && (std::numeric_limits<T>::is_signed == true) && (std::numeric_limits<IntType>::is_signed == true), bool>::type is_safe_narrowing_conversion(const T& val)
+ {
+ // Note that this check assumes IntType has a 2's complement representation,
+ // we don't want to try to convert a std::numeric_limits<IntType>::min() to
+ // a T because that conversion may not be allowed (this happens when IntType
+ // is from Boost.Multiprecision).
+ return (val < (T(1) << std::numeric_limits<IntType>::digits)) && (val >= -(T(1) << std::numeric_limits<IntType>::digits));
+ }
+ //
+ // (3) From a signed type with more digits than IntType, and IntType unsigned:
+ //
+ template <class T>
+ BOOST_CONSTEXPR static typename boost::enable_if_c<(std::numeric_limits<T>::digits > std::numeric_limits<IntType>::digits) && (std::numeric_limits<T>::is_signed == true) && (std::numeric_limits<IntType>::is_signed == false), bool>::type is_safe_narrowing_conversion(const T& val)
+ {
+ return (val < (T(1) << std::numeric_limits<IntType>::digits)) && (val >= 0);
+ }
+ //
+ // (4) From a signed type with fewer digits than IntType, and IntType unsigned:
+ //
+ template <class T>
+ BOOST_CONSTEXPR static typename boost::enable_if_c<(std::numeric_limits<T>::digits <= std::numeric_limits<IntType>::digits) && (std::numeric_limits<T>::is_signed == true) && (std::numeric_limits<IntType>::is_signed == false), bool>::type is_safe_narrowing_conversion(const T& val)
+ {
+ return val >= 0;
+ }
+ //
+ // (5) From an unsigned type with fewer digits than IntType, and IntType signed:
+ //
+ template <class T>
+ BOOST_CONSTEXPR static typename boost::enable_if_c<(std::numeric_limits<T>::digits <= std::numeric_limits<IntType>::digits) && (std::numeric_limits<T>::is_signed == false) && (std::numeric_limits<IntType>::is_signed == true), bool>::type is_safe_narrowing_conversion(const T&)
+ {
+ return true;
+ }
+ //
+ // (6) From an unsigned type with fewer digits than IntType, and IntType unsigned:
+ //
+ template <class T>
+ BOOST_CONSTEXPR static typename boost::enable_if_c<(std::numeric_limits<T>::digits <= std::numeric_limits<IntType>::digits) && (std::numeric_limits<T>::is_signed == false) && (std::numeric_limits<IntType>::is_signed == false), bool>::type is_safe_narrowing_conversion(const T&)
+ {
+ return true;
+ }
+ //
+ // (7) From an signed type with fewer digits than IntType, and IntType signed:
+ //
+ template <class T>
+ BOOST_CONSTEXPR static typename boost::enable_if_c<(std::numeric_limits<T>::digits <= std::numeric_limits<IntType>::digits) && (std::numeric_limits<T>::is_signed == true) && (std::numeric_limits<IntType>::is_signed == true), bool>::type is_safe_narrowing_conversion(const T&)
+ {
+ return true;
+ }
};
-// Assign in place
-template <typename IntType>
-inline rational<IntType>& rational<IntType>::assign(param_type n, param_type d)
-{
- return *this = rational( n, d );
-}
-
// Unary plus and minus
template <typename IntType>
BOOST_CONSTEXPR
@@ -271,7 +482,7 @@ inline rational<IntType> operator+ (const rational<IntType>& r)
template <typename IntType>
inline rational<IntType> operator- (const rational<IntType>& r)
{
- return rational<IntType>(-r.numerator(), r.denominator());
+ return rational<IntType>(static_cast<IntType>(-r.numerator()), r.denominator());
}
// Arithmetic assignment operators
@@ -373,40 +584,155 @@ rational<IntType>& rational<IntType>::operator/= (const rational<IntType>& r)
return *this;
}
-// Mixed-mode operators
-template <typename IntType>
-inline rational<IntType>&
-rational<IntType>::operator*= (param_type i)
+
+//
+// Non-member operators: previously these were provided by Boost.Operator, but these had a number of
+// drawbacks, most notably, that in order to allow inter-operability with IntType code such as this:
+//
+// rational<int> r(3);
+// assert(r == 3.5); // compiles and passes!!
+//
+// Happens to be allowed as well :-(
+//
+// There are three possible cases for each operator:
+// 1) rational op rational.
+// 2) rational op integer
+// 3) integer op rational
+// Cases (1) and (2) are folded into the one function.
+//
+template <class IntType, class Arg>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value || is_same<rational<IntType>, Arg>::value, rational<IntType> >::type
+ operator + (const rational<IntType>& a, const Arg& b)
{
- // Avoid overflow and preserve normalization
- IntType gcd = integer::gcd(i, den);
- num *= i / gcd;
- den /= gcd;
+ rational<IntType> t(a);
+ return t += b;
+}
+template <class Arg, class IntType>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value, rational<IntType> >::type
+ operator + (const Arg& b, const rational<IntType>& a)
+{
+ rational<IntType> t(a);
+ return t += b;
+}
- return *this;
+template <class IntType, class Arg>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value || is_same<rational<IntType>, Arg>::value, rational<IntType> >::type
+ operator - (const rational<IntType>& a, const Arg& b)
+{
+ rational<IntType> t(a);
+ return t -= b;
+}
+template <class Arg, class IntType>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value, rational<IntType> >::type
+ operator - (const Arg& b, const rational<IntType>& a)
+{
+ rational<IntType> t(a);
+ return -(t -= b);
}
-template <typename IntType>
-rational<IntType>&
-rational<IntType>::operator/= (param_type i)
+template <class IntType, class Arg>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value || is_same<rational<IntType>, Arg>::value, rational<IntType> >::type
+ operator * (const rational<IntType>& a, const Arg& b)
{
- // Avoid repeated construction
- IntType const zero(0);
+ rational<IntType> t(a);
+ return t *= b;
+}
+template <class Arg, class IntType>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value, rational<IntType> >::type
+ operator * (const Arg& b, const rational<IntType>& a)
+{
+ rational<IntType> t(a);
+ return t *= b;
+}
- if(i == zero) BOOST_THROW_EXCEPTION(bad_rational());
- if (num == zero) return *this;
+template <class IntType, class Arg>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value || is_same<rational<IntType>, Arg>::value, rational<IntType> >::type
+ operator / (const rational<IntType>& a, const Arg& b)
+{
+ rational<IntType> t(a);
+ return t /= b;
+}
+template <class Arg, class IntType>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value, rational<IntType> >::type
+ operator / (const Arg& b, const rational<IntType>& a)
+{
+ rational<IntType> t(b);
+ return t /= a;
+}
- // Avoid overflow and preserve normalization
- IntType const gcd = integer::gcd(num, i);
- num /= gcd;
- den *= i / gcd;
+template <class IntType, class Arg>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value || is_same<rational<IntType>, Arg>::value, bool>::type
+ operator <= (const rational<IntType>& a, const Arg& b)
+{
+ return !(a > b);
+}
+template <class Arg, class IntType>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value, bool>::type
+ operator <= (const Arg& b, const rational<IntType>& a)
+{
+ return a >= b;
+}
- if (den < zero) {
- num = -num;
- den = -den;
- }
+template <class IntType, class Arg>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value || is_same<rational<IntType>, Arg>::value, bool>::type
+ operator >= (const rational<IntType>& a, const Arg& b)
+{
+ return !(a < b);
+}
+template <class Arg, class IntType>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value, bool>::type
+ operator >= (const Arg& b, const rational<IntType>& a)
+{
+ return a <= b;
+}
- return *this;
+template <class IntType, class Arg>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value || is_same<rational<IntType>, Arg>::value, bool>::type
+ operator != (const rational<IntType>& a, const Arg& b)
+{
+ return !(a == b);
+}
+template <class Arg, class IntType>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value, bool>::type
+ operator != (const Arg& b, const rational<IntType>& a)
+{
+ return !(b == a);
+}
+
+template <class Arg, class IntType>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value, bool>::type
+ operator < (const Arg& b, const rational<IntType>& a)
+{
+ return a > b;
+}
+template <class Arg, class IntType>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value, bool>::type
+ operator > (const Arg& b, const rational<IntType>& a)
+{
+ return a < b;
+}
+template <class Arg, class IntType>
+inline typename boost::enable_if_c <
+ rational_detail::is_compatible_integer<Arg, IntType>::value, bool>::type
+ operator == (const Arg& b, const rational<IntType>& a)
+{
+ return a == b;
}
// Comparison operators
@@ -495,43 +821,12 @@ bool rational<IntType>::operator< (const rational<IntType>& r) const
}
template <typename IntType>
-bool rational<IntType>::operator< (param_type i) const
-{
- // Avoid repeated construction
- int_type const zero( 0 );
-
- // Break value into mixed-fraction form, w/ always-nonnegative remainder
- BOOST_ASSERT( this->den > zero );
- int_type q = this->num / this->den, r = this->num % this->den;
- while ( r < zero ) { r += this->den; --q; }
-
- // Compare with just the quotient, since the remainder always bumps the
- // value up. [Since q = floor(n/d), and if n/d < i then q < i, if n/d == i
- // then q == i, if n/d == i + r/d then q == i, and if n/d >= i + 1 then
- // q >= i + 1 > i; therefore n/d < i iff q < i.]
- return q < i;
-}
-
-template <typename IntType>
-bool rational<IntType>::operator> (param_type i) const
-{
- return operator==(i)? false: !operator<(i);
-}
-
-template <typename IntType>
BOOST_CONSTEXPR
inline bool rational<IntType>::operator== (const rational<IntType>& r) const
{
return ((num == r.num) && (den == r.den));
}
-template <typename IntType>
-BOOST_CONSTEXPR
-inline bool rational<IntType>::operator== (param_type i) const
-{
- return ((den == IntType(1)) && (num == i));
-}
-
// Invariant check
template <typename IntType>
inline bool rational<IntType>::test_invariant() const
diff --git a/boost/regex/config.hpp b/boost/regex/config.hpp
index 9dc48dc8ab..589b1e3a4f 100644
--- a/boost/regex/config.hpp
+++ b/boost/regex/config.hpp
@@ -152,7 +152,7 @@
# if defined(BOOST_REGEX_NO_W32) || BOOST_PLAT_WINDOWS_RUNTIME
# define BOOST_REGEX_NO_FILEITER
# endif
-#else // defined(_WIN32)
+#else /* defined(_WIN32) */
# if !defined(BOOST_HAS_DIRENT_H)
# define BOOST_REGEX_NO_FILEITER
# endif
@@ -255,7 +255,7 @@
*
****************************************************************************/
-#if defined(BOOST_MSVC) && defined(_MSC_EXTENSIONS)
+#if defined(_MSC_VER) && defined(_MSC_EXTENSIONS)
#if defined(_DEBUG) || defined(__MSVC_RUNTIME_CHECKS) || defined(_MANAGED) || defined(BOOST_REGEX_NO_FASTCALL)
# define BOOST_REGEX_CALL __cdecl
#else
@@ -393,7 +393,7 @@ BOOST_REGEX_DECL void BOOST_REGEX_CALL reset_stack_guard_page();
****************************************************************************/
#if !defined(BOOST_REGEX_RECURSIVE) && !defined(BOOST_REGEX_NON_RECURSIVE)
-# if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && !defined(_STLP_DEBUG) && !defined(__STL_DEBUG) && !(defined(BOOST_MSVC) && (BOOST_MSVC >= 1400))
+# if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && !defined(_STLP_DEBUG) && !defined(__STL_DEBUG) && !(defined(_MSC_VER) && (_MSC_VER >= 1400))
# define BOOST_REGEX_RECURSIVE
# else
# define BOOST_REGEX_NON_RECURSIVE
diff --git a/boost/regex/icu.hpp b/boost/regex/icu.hpp
index a57fe57791..8be8e60ae9 100644
--- a/boost/regex/icu.hpp
+++ b/boost/regex/icu.hpp
@@ -410,7 +410,7 @@ void copy_results(MR1& out, MR2 const& in)
if(in[i].captures().size())
{
out[i].get_captures().assign(in[i].captures().size(), typename MR1::value_type());
- for(int j = 0; j < out[i].captures().size(); ++j)
+ for(int j = 0; j < (int)out[i].captures().size(); ++j)
{
out[i].get_captures()[j].first = in[i].captures()[j].first.base();
out[i].get_captures()[j].second = in[i].captures()[j].second.base();
diff --git a/boost/regex/pending/unicode_iterator.hpp b/boost/regex/pending/unicode_iterator.hpp
index 04af426015..becb17ad5f 100644
--- a/boost/regex/pending/unicode_iterator.hpp
+++ b/boost/regex/pending/unicode_iterator.hpp
@@ -117,7 +117,10 @@ inline unsigned utf8_trailing_byte_count(boost::uint8_t c)
#pragma warning(push)
#pragma warning(disable:4100)
#endif
-BOOST_NORETURN inline void invalid_utf32_code_point(::boost::uint32_t val)
+#ifndef BOOST_NO_EXCEPTIONS
+BOOST_NORETURN
+#endif
+inline void invalid_utf32_code_point(::boost::uint32_t val)
{
#ifndef BOOST_NO_STD_LOCALE
std::stringstream ss;
diff --git a/boost/regex/v4/basic_regex_creator.hpp b/boost/regex/v4/basic_regex_creator.hpp
index 51704a849f..132ff84f07 100644
--- a/boost/regex/v4/basic_regex_creator.hpp
+++ b/boost/regex/v4/basic_regex_creator.hpp
@@ -77,15 +77,15 @@ public:
void add_single(const digraph_type& s)
{
- m_singles.insert(m_singles.end(), s);
+ m_singles.insert(s);
if(s.second)
m_has_digraphs = true;
m_empty = false;
}
void add_range(const digraph_type& first, const digraph_type& end)
{
- m_ranges.insert(m_ranges.end(), first);
- m_ranges.insert(m_ranges.end(), end);
+ m_ranges.push_back(first);
+ m_ranges.push_back(end);
if(first.second)
{
m_has_digraphs = true;
@@ -110,7 +110,7 @@ public:
}
void add_equivalent(const digraph_type& s)
{
- m_equivalents.insert(m_equivalents.end(), s);
+ m_equivalents.insert(s);
if(s.second)
{
m_has_digraphs = true;
@@ -136,11 +136,12 @@ public:
return m_negate;
}
typedef typename std::vector<digraph_type>::const_iterator list_iterator;
- list_iterator singles_begin()const
+ typedef typename std::set<digraph_type>::const_iterator set_iterator;
+ set_iterator singles_begin()const
{
return m_singles.begin();
}
- list_iterator singles_end()const
+ set_iterator singles_end()const
{
return m_singles.end();
}
@@ -152,11 +153,11 @@ public:
{
return m_ranges.end();
}
- list_iterator equivalents_begin()const
+ set_iterator equivalents_begin()const
{
return m_equivalents.begin();
}
- list_iterator equivalents_end()const
+ set_iterator equivalents_end()const
{
return m_equivalents.end();
}
@@ -173,14 +174,14 @@ public:
return m_empty;
}
private:
- std::vector<digraph_type> m_singles; // a list of single characters to match
+ std::set<digraph_type> m_singles; // a list of single characters to match
std::vector<digraph_type> m_ranges; // a list of end points of our ranges
bool m_negate; // true if the set is to be negated
bool m_has_digraphs; // true if we have digraphs present
m_type m_classes; // character classes to match
m_type m_negated_classes; // negated character classes to match
bool m_empty; // whether we've added anything yet
- std::vector<digraph_type> m_equivalents; // a list of equivalence classes
+ std::set<digraph_type> m_equivalents; // a list of equivalence classes
};
template <class charT, class traits>
@@ -239,7 +240,7 @@ protected:
unsigned m_backrefs; // bitmask of permitted backrefs
boost::uintmax_t m_bad_repeats; // bitmask of repeats we can't deduce a startmap for;
bool m_has_recursions; // set when we have recursive expresisons to fixup
- std::vector<bool> m_recursion_checks; // notes which recursions we've followed while analysing this expression
+ std::vector<unsigned char> m_recursion_checks; // notes which recursions we've followed while analysing this expression
typename traits::char_class_type m_word_mask; // mask used to determine if a character is a word character
typename traits::char_class_type m_mask_space; // mask used to determine if a character is a word character
typename traits::char_class_type m_lower_mask; // mask used to determine if a character is a lowercase character
@@ -365,6 +366,7 @@ re_syntax_base* basic_regex_creator<charT, traits>::append_set(
{
typedef typename traits::string_type string_type;
typedef typename basic_char_set<charT, traits>::list_iterator item_iterator;
+ typedef typename basic_char_set<charT, traits>::set_iterator set_iterator;
typedef typename traits::char_class_type m_type;
re_set_long<m_type>* result = static_cast<re_set_long<m_type>*>(append_state(syntax_element_long_set, sizeof(re_set_long<m_type>)));
@@ -395,20 +397,25 @@ re_syntax_base* basic_regex_creator<charT, traits>::append_set(
// now extend with all the singles:
//
item_iterator first, last;
- first = char_set.singles_begin();
- last = char_set.singles_end();
- while(first != last)
+ set_iterator sfirst, slast;
+ sfirst = char_set.singles_begin();
+ slast = char_set.singles_end();
+ while(sfirst != slast)
{
- charT* p = static_cast<charT*>(this->m_pdata->m_data.extend(sizeof(charT) * (first->second ? 3 : 2)));
- p[0] = m_traits.translate(first->first, m_icase);
- if(first->second)
+ charT* p = static_cast<charT*>(this->m_pdata->m_data.extend(sizeof(charT) * (sfirst->first == static_cast<charT>(0) ? 1 : sfirst->second ? 3 : 2)));
+ p[0] = m_traits.translate(sfirst->first, m_icase);
+ if(sfirst->first == static_cast<charT>(0))
+ {
+ p[0] = 0;
+ }
+ else if(sfirst->second)
{
- p[1] = m_traits.translate(first->second, m_icase);
+ p[1] = m_traits.translate(sfirst->second, m_icase);
p[2] = 0;
}
else
p[1] = 0;
- ++first;
+ ++sfirst;
}
//
// now extend with all the ranges:
@@ -472,24 +479,24 @@ re_syntax_base* basic_regex_creator<charT, traits>::append_set(
//
// now process the equivalence classes:
//
- first = char_set.equivalents_begin();
- last = char_set.equivalents_end();
- while(first != last)
+ sfirst = char_set.equivalents_begin();
+ slast = char_set.equivalents_end();
+ while(sfirst != slast)
{
string_type s;
- if(first->second)
+ if(sfirst->second)
{
- charT cs[3] = { first->first, first->second, charT(0), };
+ charT cs[3] = { sfirst->first, sfirst->second, charT(0), };
s = m_traits.transform_primary(cs, cs+2);
}
else
- s = m_traits.transform_primary(&first->first, &first->first+1);
+ s = m_traits.transform_primary(&sfirst->first, &sfirst->first+1);
if(s.empty())
return 0; // invalid or unsupported equivalence class
charT* p = static_cast<charT*>(this->m_pdata->m_data.extend(sizeof(charT) * (s.size()+1) ) );
BOOST_REGEX_DETAIL_NS::copy(s.begin(), s.end(), p);
p[s.size()] = charT(0);
- ++first;
+ ++sfirst;
}
//
// finally reset the address of our last state:
@@ -518,7 +525,8 @@ re_syntax_base* basic_regex_creator<charT, traits>::append_set(
{
typedef typename traits::string_type string_type;
typedef typename basic_char_set<charT, traits>::list_iterator item_iterator;
-
+ typedef typename basic_char_set<charT, traits>::set_iterator set_iterator;
+
re_set* result = static_cast<re_set*>(append_state(syntax_element_set, sizeof(re_set)));
bool negate = char_set.is_negated();
std::memset(result->_map, 0, sizeof(result->_map));
@@ -526,17 +534,18 @@ re_syntax_base* basic_regex_creator<charT, traits>::append_set(
// handle singles first:
//
item_iterator first, last;
- first = char_set.singles_begin();
- last = char_set.singles_end();
- while(first != last)
+ set_iterator sfirst, slast;
+ sfirst = char_set.singles_begin();
+ slast = char_set.singles_end();
+ while(sfirst != slast)
{
for(unsigned int i = 0; i < (1 << CHAR_BIT); ++i)
{
if(this->m_traits.translate(static_cast<charT>(i), this->m_icase)
- == this->m_traits.translate(first->first, this->m_icase))
+ == this->m_traits.translate(sfirst->first, this->m_icase))
result->_map[i] = true;
}
- ++first;
+ ++sfirst;
}
//
// OK now handle ranges:
@@ -623,13 +632,13 @@ re_syntax_base* basic_regex_creator<charT, traits>::append_set(
//
// now process the equivalence classes:
//
- first = char_set.equivalents_begin();
- last = char_set.equivalents_end();
- while(first != last)
+ sfirst = char_set.equivalents_begin();
+ slast = char_set.equivalents_end();
+ while(sfirst != slast)
{
string_type s;
- BOOST_ASSERT(static_cast<charT>(0) == first->second);
- s = m_traits.transform_primary(&first->first, &first->first+1);
+ BOOST_ASSERT(static_cast<charT>(0) == sfirst->second);
+ s = m_traits.transform_primary(&sfirst->first, &sfirst->first+1);
if(s.empty())
return 0; // invalid or unsupported equivalence class
for(unsigned i = 0; i < (1u << CHAR_BIT); ++i)
@@ -639,7 +648,7 @@ re_syntax_base* basic_regex_creator<charT, traits>::append_set(
if(s == s2)
result->_map[i] = true;
}
- ++first;
+ ++sfirst;
}
if(negate)
{
@@ -690,7 +699,7 @@ void basic_regex_creator<charT, traits>::finalize(const charT* p1, const charT*
m_bad_repeats = 0;
if(m_has_recursions)
- m_recursion_checks.assign(1 + m_pdata->m_mark_count, false);
+ m_recursion_checks.assign(1 + m_pdata->m_mark_count, 0u);
create_startmap(m_pdata->m_first_state, m_pdata->m_startmap, &(m_pdata->m_can_be_null), mask_all);
// get the restart type:
m_pdata->m_restart_type = get_restart_type(m_pdata->m_first_state);
@@ -792,50 +801,57 @@ void basic_regex_creator<charT, traits>::fixup_recursions(re_syntax_base* state)
//
idx = m_pdata->get_id(static_cast<int>(idx));
}
- while(p)
+ if(idx < 0)
+ {
+ ok = false;
+ }
+ else
{
- if((p->type == syntax_element_startmark) && (static_cast<re_brace*>(p)->index == idx))
+ while(p)
{
- //
- // We've found the target of the recursion, set the jump target:
- //
- static_cast<re_jump*>(state)->alt.p = p;
- ok = true;
- //
- // Now scan the target for nested repeats:
- //
- p = p->next.p;
- int next_rep_id = 0;
- while(p)
+ if((p->type == syntax_element_startmark) && (static_cast<re_brace*>(p)->index == idx))
{
- switch(p->type)
+ //
+ // We've found the target of the recursion, set the jump target:
+ //
+ static_cast<re_jump*>(state)->alt.p = p;
+ ok = true;
+ //
+ // Now scan the target for nested repeats:
+ //
+ p = p->next.p;
+ int next_rep_id = 0;
+ while(p)
{
- case syntax_element_rep:
- case syntax_element_dot_rep:
- case syntax_element_char_rep:
- case syntax_element_short_set_rep:
- case syntax_element_long_set_rep:
- next_rep_id = static_cast<re_repeat*>(p)->state_id;
- break;
- case syntax_element_endmark:
- if(static_cast<const re_brace*>(p)->index == idx)
- next_rep_id = -1;
- break;
- default:
- break;
+ switch(p->type)
+ {
+ case syntax_element_rep:
+ case syntax_element_dot_rep:
+ case syntax_element_char_rep:
+ case syntax_element_short_set_rep:
+ case syntax_element_long_set_rep:
+ next_rep_id = static_cast<re_repeat*>(p)->state_id;
+ break;
+ case syntax_element_endmark:
+ if(static_cast<const re_brace*>(p)->index == idx)
+ next_rep_id = -1;
+ break;
+ default:
+ break;
+ }
+ if(next_rep_id)
+ break;
+ p = p->next.p;
+ }
+ if(next_rep_id > 0)
+ {
+ static_cast<re_recurse*>(state)->state_id = next_rep_id - 1;
}
- if(next_rep_id)
- break;
- p = p->next.p;
- }
- if(next_rep_id > 0)
- {
- static_cast<re_recurse*>(state)->state_id = next_rep_id - 1;
- }
- break;
+ break;
+ }
+ p = p->next.p;
}
- p = p->next.p;
}
if(!ok)
{
@@ -934,7 +950,7 @@ void basic_regex_creator<charT, traits>::create_startmaps(re_syntax_base* state)
{
// Initialize m_recursion_checks if we need it:
if(m_has_recursions)
- m_recursion_checks.assign(1 + m_pdata->m_mark_count, false);
+ m_recursion_checks.assign(1 + m_pdata->m_mark_count, 0u);
const std::pair<bool, re_syntax_base*>& p = v.back();
m_icase = p.first;
@@ -947,7 +963,7 @@ void basic_regex_creator<charT, traits>::create_startmaps(re_syntax_base* state)
m_bad_repeats = 0;
if(m_has_recursions)
- m_recursion_checks.assign(1 + m_pdata->m_mark_count, false);
+ m_recursion_checks.assign(1 + m_pdata->m_mark_count, 0u);
create_startmap(static_cast<re_alt*>(state)->alt.p, static_cast<re_alt*>(state)->_map, &static_cast<re_alt*>(state)->can_be_null, mask_skip);
// adjust the type of the state to allow for faster matching:
state->type = this->get_repeat_type(state);
@@ -1102,11 +1118,9 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
}
case syntax_element_recurse:
{
- if(state->type == syntax_element_startmark)
- recursion_sub = static_cast<re_brace*>(state)->index;
- else
- recursion_sub = 0;
- if(m_recursion_checks[recursion_sub])
+ BOOST_ASSERT(static_cast<const re_jump*>(state)->alt.p->type == syntax_element_startmark);
+ recursion_sub = static_cast<re_brace*>(static_cast<const re_jump*>(state)->alt.p)->index;
+ if(m_recursion_checks[recursion_sub] & 1u)
{
// Infinite recursion!!
if(0 == this->m_pdata->m_status) // update the error code if not already set
@@ -1131,10 +1145,10 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
recursion_start = state;
recursion_restart = state->next.p;
state = static_cast<re_jump*>(state)->alt.p;
- m_recursion_checks[recursion_sub] = true;
+ m_recursion_checks[recursion_sub] |= 1u;
break;
}
- m_recursion_checks[recursion_sub] = true;
+ m_recursion_checks[recursion_sub] |= 1u;
// can't handle nested recursion here...
BOOST_FALLTHROUGH;
}
@@ -1328,8 +1342,9 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
}
p = p->next.p;
}
- if(ok)
+ if(ok && ((m_recursion_checks[static_cast<re_brace*>(state)->index] & 2u) == 0))
{
+ m_recursion_checks[static_cast<re_brace*>(state)->index] |= 2u;
create_startmap(p->next.p, l_map, pnull, mask);
}
}
@@ -1419,7 +1434,7 @@ bool basic_regex_creator<charT, traits>::is_bad_repeat(re_syntax_base* pt)
case syntax_element_long_set_rep:
{
unsigned state_id = static_cast<re_repeat*>(pt)->state_id;
- if(state_id > sizeof(m_bad_repeats) * CHAR_BIT)
+ if(state_id >= sizeof(m_bad_repeats) * CHAR_BIT)
return true; // run out of bits, assume we can't traverse this one.
static const boost::uintmax_t one = 1uL;
return m_bad_repeats & (one << state_id);
diff --git a/boost/regex/v4/basic_regex_parser.hpp b/boost/regex/v4/basic_regex_parser.hpp
index 0071a8ce8e..4ab1670e1f 100644
--- a/boost/regex/v4/basic_regex_parser.hpp
+++ b/boost/regex/v4/basic_regex_parser.hpp
@@ -511,7 +511,8 @@ bool basic_regex_parser<charT, traits>::parse_open_paren()
this->fail(regex_constants::error_paren, ::boost::BOOST_REGEX_DETAIL_NS::distance(m_base, m_end));
return false;
}
- BOOST_ASSERT(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark);
+ if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
+ return false;
#ifndef BOOST_NO_STD_DISTANCE
if(markid && (this->flags() & regbase::save_subexpression_location))
this->m_pdata->m_subs.at(markid - 1).second = std::distance(m_base, m_position);
@@ -901,7 +902,7 @@ escape_type_class_jump:
}
if(negative)
i = 1 + m_mark_count - i;
- if(((i > 0) && (this->m_backrefs & (1u << (i-1)))) || ((i > 10000) && (this->m_pdata->get_id(i) > 0) && (this->m_backrefs & (1u << (this->m_pdata->get_id(i)-1)))))
+ if(((i > 0) && (i < std::numeric_limits<unsigned>::digits) && (i - 1 < static_cast<boost::intmax_t>(sizeof(unsigned) * CHAR_BIT)) && (this->m_backrefs & (1u << (i-1)))) || ((i > 10000) && (this->m_pdata->get_id(i) > 0) && (this->m_pdata->get_id(i)-1 < static_cast<boost::intmax_t>(sizeof(unsigned) * CHAR_BIT)) && (this->m_backrefs & (1u << (this->m_pdata->get_id(i)-1)))))
{
m_position = pc;
re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_backref, sizeof(re_brace)));
@@ -2596,7 +2597,7 @@ option_group_jump:
re_alt* alt = static_cast<re_alt*>(this->insert_state(expected_alt_point, syntax_element_alt, sizeof(re_alt)));
alt->alt.i = this->m_pdata->m_data.size() - this->getoffset(alt);
}
- else if(this->getaddress(static_cast<re_alt*>(b)->alt.i, b)->type == syntax_element_alt)
+ else if(((std::ptrdiff_t)this->m_pdata->m_data.size() > (static_cast<re_alt*>(b)->alt.i + this->getoffset(b))) && (static_cast<re_alt*>(b)->alt.i > 0) && this->getaddress(static_cast<re_alt*>(b)->alt.i, b)->type == syntax_element_alt)
{
// Can't have seen more than one alternative:
// Rewind to start of (? sequence:
@@ -2860,6 +2861,10 @@ bool basic_regex_parser<charT, traits>::parse_perl_verb()
}
break;
}
+ // Rewind to start of (* sequence:
+ --m_position;
+ while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
+ fail(regex_constants::error_perl_extension, m_position - m_base);
return false;
}
diff --git a/boost/regex/v4/match_flags.hpp b/boost/regex/v4/match_flags.hpp
index 1c0046b75f..1938b27a44 100644
--- a/boost/regex/v4/match_flags.hpp
+++ b/boost/regex/v4/match_flags.hpp
@@ -68,7 +68,18 @@ typedef enum _match_flags
format_no_copy = format_all << 1, /* don't copy non-matching segments. */
format_first_only = format_no_copy << 1, /* Only replace first occurance. */
format_is_if = format_first_only << 1, /* internal use only. */
- format_literal = format_is_if << 1 /* treat string as a literal */
+ format_literal = format_is_if << 1, /* treat string as a literal */
+
+ match_not_any = match_not_bol | match_not_eol | match_not_bob
+ | match_not_eob | match_not_bow | match_not_eow | match_not_dot_newline
+ | match_not_dot_null | match_prev_avail | match_init | match_not_null
+ | match_continuous | match_partial | match_stop | match_not_initial_null
+ | match_stop | match_all | match_perl | match_posix | match_nosubs
+ | match_extra | match_single_line | match_unused1 | match_unused2
+ | match_unused3 | match_max | format_perl | format_default | format_sed
+ | format_all | format_no_copy | format_first_only | format_is_if
+ | format_literal
+
} match_flags;
diff --git a/boost/regex/v4/perl_matcher.hpp b/boost/regex/v4/perl_matcher.hpp
index 96a086b81a..32517c62e7 100644
--- a/boost/regex/v4/perl_matcher.hpp
+++ b/boost/regex/v4/perl_matcher.hpp
@@ -161,9 +161,9 @@ iterator BOOST_REGEX_CALL re_is_set_member(iterator next,
if(*p == static_cast<charT>(0))
{
// treat null string as special case:
- if(traits_inst.translate(*ptr, icase) != *p)
+ if(traits_inst.translate(*ptr, icase))
{
- while(*p == static_cast<charT>(0))++p;
+ ++p;
continue;
}
return set_->isnot ? next : (ptr == next) ? ++next : ptr;
@@ -348,6 +348,7 @@ struct recursion_info
const re_syntax_base* preturn_address;
Results results;
repeater_count<iterator>* repeater_stack;
+ iterator location_of_start;
};
#ifdef BOOST_MSVC
diff --git a/boost/regex/v4/perl_matcher_common.hpp b/boost/regex/v4/perl_matcher_common.hpp
index 6febff4cc5..7974e74835 100644
--- a/boost/regex/v4/perl_matcher_common.hpp
+++ b/boost/regex/v4/perl_matcher_common.hpp
@@ -90,7 +90,7 @@ void perl_matcher<BidiIterator, Allocator, traits>::construct_init(const basic_r
match_any_mask = static_cast<unsigned char>((f & match_not_dot_newline) ? BOOST_REGEX_DETAIL_NS::test_not_newline : BOOST_REGEX_DETAIL_NS::test_newline);
// Disable match_any if requested in the state machine:
if(e.get_data().m_disable_match_any)
- m_match_flags &= ~regex_constants::match_any;
+ m_match_flags &= regex_constants::match_not_any;
}
template <class BidiIterator, class Allocator, class traits>
diff --git a/boost/regex/v4/perl_matcher_non_recursive.hpp b/boost/regex/v4/perl_matcher_non_recursive.hpp
index aa7af3b42f..c12dea8e72 100644
--- a/boost/regex/v4/perl_matcher_non_recursive.hpp
+++ b/boost/regex/v4/perl_matcher_non_recursive.hpp
@@ -131,8 +131,7 @@ template <class Results>
struct saved_recursion : public saved_state
{
saved_recursion(int idx, const re_syntax_base* p, Results* pr)
- : saved_state(14), recursion_id(idx), preturn_address(p), results(*pr)
- {}
+ : saved_state(14), recursion_id(idx), preturn_address(p), results(*pr) {}
int recursion_id;
const re_syntax_base* preturn_address;
Results results;
@@ -405,7 +404,11 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
m_independent = true;
const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
pstate = pstate->next.p->next.p;
- bool r = match_all_states();
+ bool r = false;
+#if !defined(BOOST_NO_EXCEPTIONS)
+ try{
+#endif
+ r = match_all_states();
if(!r && !m_independent)
{
// Must be unwinding from a COMMIT/SKIP/PRUNE and the independent
@@ -413,8 +416,20 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
while(unwind(false));
return false;
}
+#if !defined(BOOST_NO_EXCEPTIONS)
+ }
+ catch(...)
+ {
pstate = next_pstate;
- m_independent = old_independent;
+ // unwind all pushed states, apart from anything else this
+ // ensures that all the states are correctly destructed
+ // not just the memory freed.
+ while(unwind(true)) {}
+ throw;
+ }
+#endif
+ pstate = next_pstate;
+ m_independent = old_independent;
#ifdef BOOST_REGEX_MATCH_EXTRA
if(r && (m_match_flags & match_extra))
{
@@ -428,8 +443,23 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
for(i = 0; i < temp_match.size(); ++i)
(*m_presult)[i].get_captures().clear();
// match everything else:
- r = match_all_states();
- // now place the stored captures back:
+#if !defined(BOOST_NO_EXCEPTIONS)
+ try{
+#endif
+ r = match_all_states();
+#if !defined(BOOST_NO_EXCEPTIONS)
+ }
+ catch(...)
+ {
+ pstate = next_pstate;
+ // unwind all pushed states, apart from anything else this
+ // ensures that all the states are correctly destructed
+ // not just the memory freed.
+ while(unwind(true)) {}
+ throw;
+ }
+#endif
+ // now place the stored captures back:
for(i = 0; i < temp_match.size(); ++i)
{
typedef typename sub_match<BidiIterator>::capture_sequence_type seq;
@@ -464,14 +494,29 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
BidiIterator saved_position = position;
const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
pstate = pstate->next.p->next.p;
- bool r = match_all_states();
- position = saved_position;
- if(negated)
- r = !r;
- if(r)
+#if !defined(BOOST_NO_EXCEPTIONS)
+ try{
+#endif
+ bool r = match_all_states();
+ position = saved_position;
+ if(negated)
+ r = !r;
+ if(r)
+ pstate = next_pstate;
+ else
+ pstate = alt->alt.p;
+#if !defined(BOOST_NO_EXCEPTIONS)
+ }
+ catch(...)
+ {
pstate = next_pstate;
- else
- pstate = alt->alt.p;
+ // unwind all pushed states, apart from anything else this
+ // ensures that all the states are correctly destructed
+ // not just the memory freed.
+ while(unwind(true)){}
+ throw;
+ }
+#endif
break;
}
}
@@ -953,6 +998,19 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
{
BOOST_ASSERT(pstate->type == syntax_element_recurse);
//
+ // See if we've seen this recursion before at this location, if we have then
+ // we need to prevent infinite recursion:
+ //
+ for(typename std::vector<recursion_info<results_type> >::reverse_iterator i = recursion_stack.rbegin(); i != recursion_stack.rend(); ++i)
+ {
+ if(i->idx == static_cast<const re_brace*>(static_cast<const re_jump*>(pstate)->alt.p)->index)
+ {
+ if(i->location_of_start == position)
+ return false;
+ break;
+ }
+ }
+ //
// Backup call stack:
//
push_recursion_pop();
@@ -968,6 +1026,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
recursion_stack.back().results = *m_presult;
pstate = static_cast<const re_jump*>(pstate)->alt.p;
recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
+ recursion_stack.back().location_of_start = position;
//if(static_cast<const re_recurse*>(pstate)->state_id > 0)
{
push_repeater_count(-(2 + static_cast<const re_brace*>(pstate)->index), &next_count);
@@ -1705,6 +1764,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion(bool r)
recursion_stack.back().idx = pmp->recursion_id;
recursion_stack.back().preturn_address = pmp->preturn_address;
recursion_stack.back().results = pmp->results;
+ recursion_stack.back().location_of_start = position;
}
boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
m_backup_state = pmp;
diff --git a/boost/regex/v4/perl_matcher_recursive.hpp b/boost/regex/v4/perl_matcher_recursive.hpp
index 33b9158193..8eb23abfdc 100644
--- a/boost/regex/v4/perl_matcher_recursive.hpp
+++ b/boost/regex/v4/perl_matcher_recursive.hpp
@@ -900,10 +900,27 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
{
recursion_stack.reserve(50);
}
+ //
+ // See if we've seen this recursion before at this location, if we have then
+ // we need to prevent infinite recursion:
+ //
+ for(typename std::vector<recursion_info<results_type> >::reverse_iterator i = recursion_stack.rbegin(); i != recursion_stack.rend(); ++i)
+ {
+ if(i->idx == static_cast<const re_brace*>(static_cast<const re_jump*>(pstate)->alt.p)->index)
+ {
+ if(i->location_of_start == position)
+ return false;
+ break;
+ }
+ }
+ //
+ // Now get on with it:
+ //
recursion_stack.push_back(recursion_info<results_type>());
recursion_stack.back().preturn_address = pstate->next.p;
recursion_stack.back().results = *m_presult;
recursion_stack.back().repeater_stack = next_count;
+ recursion_stack.back().location_of_start = position;
pstate = static_cast<const re_jump*>(pstate)->alt.p;
recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
@@ -979,6 +996,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
recursion_stack.push_back(recursion_info<results_type>());
recursion_stack.back().preturn_address = saved_state;
recursion_stack.back().results = *m_presult;
+ recursion_stack.back().location_of_start = position;
return false;
}
return true;
diff --git a/boost/regex/v4/regex_workaround.hpp b/boost/regex/v4/regex_workaround.hpp
index 821be608c1..f900720bfd 100644
--- a/boost/regex/v4/regex_workaround.hpp
+++ b/boost/regex/v4/regex_workaround.hpp
@@ -33,6 +33,7 @@
#include <algorithm>
#include <iosfwd>
#include <vector>
+#include <set>
#include <map>
#include <boost/limits.hpp>
#include <boost/assert.hpp>
diff --git a/boost/serialization/archive_input_unordered_map.hpp b/boost/serialization/archive_input_unordered_map.hpp
index ef0fd93ebd..ccf806b181 100644
--- a/boost/serialization/archive_input_unordered_map.hpp
+++ b/boost/serialization/archive_input_unordered_map.hpp
@@ -19,8 +19,10 @@
// See http://www.boost.org for updates, documentation, and revision history.
#include <boost/config.hpp>
-
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/detail/stack_constructor.hpp>
#include <boost/serialization/utility.hpp>
+#include <boost/move/utility_core.hpp>
namespace boost {
namespace serialization {
@@ -39,11 +41,7 @@ struct archive_input_unordered_map
detail::stack_construct<Archive, type> t(ar, v);
ar >> boost::serialization::make_nvp("item", t.reference());
std::pair<typename Container::const_iterator, bool> result =
- #ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP
- s.insert(t.reference());
- #else
- s.emplace(t.reference());
- #endif
+ s.insert(boost::move(t.reference()));
// note: the following presumes that the map::value_type was NOT tracked
// in the archive. This is the usual case, but here there is no way
// to determine that.
@@ -69,11 +67,7 @@ struct archive_input_unordered_multimap
detail::stack_construct<Archive, type> t(ar, v);
ar >> boost::serialization::make_nvp("item", t.reference());
typename Container::const_iterator result =
- #ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP
- s.insert(t.reference());
- #else
- s.emplace(t.reference());
- #endif
+ s.insert(t.reference());
// note: the following presumes that the map::value_type was NOT tracked
// in the archive. This is the usual case, but here there is no way
// to determine that.
diff --git a/boost/serialization/archive_input_unordered_set.hpp b/boost/serialization/archive_input_unordered_set.hpp
index 961b58f1a8..7f0003cc6a 100644
--- a/boost/serialization/archive_input_unordered_set.hpp
+++ b/boost/serialization/archive_input_unordered_set.hpp
@@ -17,6 +17,11 @@
// See http://www.boost.org for updates, documentation, and revision history.
+#include <utility>
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/detail/stack_constructor.hpp>
+#include <boost/move/utility_core.hpp>
+
namespace boost {
namespace serialization {
@@ -36,11 +41,7 @@ struct archive_input_unordered_set
// borland fails silently w/o full namespace
ar >> boost::serialization::make_nvp("item", t.reference());
std::pair<typename Container::const_iterator, bool> result =
- #ifdef BOOST_NO_CXX11_HDR_UNORDERED_SET
- s.insert(t.reference());
- #else
- s.emplace(t.reference());
- #endif
+ s.insert(boost::move(t.reference()));
if(result.second)
ar.reset_object_address(& (* result.first), & t.reference());
}
@@ -59,11 +60,7 @@ struct archive_input_unordered_multiset
detail::stack_construct<Archive, type> t(ar, v);
ar >> boost::serialization::make_nvp("item", t.reference());
typename Container::const_iterator result =
- #ifdef BOOST_NO_CXX11_HDR_UNORDERED_SET
- s.insert(t.reference());
- #else
- s.emplace(t.reference());
- #endif
+ s.insert(boost::move(t.reference()));
ar.reset_object_address(& (* result), & t.reference());
}
};
diff --git a/boost/serialization/array.hpp b/boost/serialization/array.hpp
index 2cd023aca9..61708b3075 100644
--- a/boost/serialization/array.hpp
+++ b/boost/serialization/array.hpp
@@ -6,136 +6,30 @@
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-//#include <iostream>
+// for serialization of <array>. If <array> not supported by the standard
+// library - this file becomes empty. This is to avoid breaking backward
+// compatibiliy for applications which used this header to support
+// serialization of native arrays. Code to serialize native arrays is
+// now always include by default. RR
#include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
#if defined(BOOST_NO_STDC_NAMESPACE)
+
+#include <iostream>
+#include <cstddef> // std::size_t
namespace std{
using ::size_t;
} // namespace std
#endif
+#ifndef BOOST_NO_CXX11_HDR_ARRAY
+
+#include <array>
#include <boost/serialization/nvp.hpp>
-#include <boost/serialization/split_member.hpp>
-#include <boost/serialization/wrapper.hpp>
-#include <boost/serialization/collection_size_type.hpp>
-#include <boost/mpl/always.hpp>
-#include <boost/mpl/apply.hpp>
-#include <boost/mpl/bool_fwd.hpp>
-#include <boost/type_traits/remove_const.hpp>
-#include <boost/type_traits/is_integral.hpp>
-#include <boost/static_assert.hpp>
namespace boost { namespace serialization {
-// traits to specify whether to use an optimized array serialization
-
-template <class Archive>
-struct use_array_optimization : boost::mpl::always<boost::mpl::false_> {};
-
-template<class T>
-class array_wrapper :
- public wrapper_traits<const array_wrapper< T > >
-{
-private:
- array_wrapper & operator=(const array_wrapper & rhs);
-public:
- // note: I would like to make the copy constructor private but this breaks
- // make_array. So I try to make make_array a friend - but that doesn't
- // build. Need a C++ guru to explain this!
- template<class S>
- friend const boost::serialization::array_wrapper<T> make_array( T* t, S s);
-
- array_wrapper(const array_wrapper & rhs) :
- m_t(rhs.m_t),
- m_element_count(rhs.m_element_count)
- {}
-public:
- array_wrapper(T * t, std::size_t s) :
- m_t(t),
- m_element_count(s)
- {}
-
- // default implementation
- template<class Archive>
- void serialize_optimized(Archive &ar, const unsigned int, mpl::false_ ) const
- {
- // default implemention does the loop
- std::size_t c = count();
- T * t = address();
- while(0 < c--)
- ar & boost::serialization::make_nvp("item", *t++);
- }
-
- // optimized implementation
- template<class Archive>
- void serialize_optimized(Archive &ar, const unsigned int version, mpl::true_ )
- {
- boost::serialization::split_member(ar, *this, version);
- }
-
- // default implementation
- template<class Archive>
- void save(Archive &ar, const unsigned int version) const
- {
- ar.save_array(*this,version);
- }
-
- // default implementation
- template<class Archive>
- void load(Archive &ar, const unsigned int version)
- {
- ar.load_array(*this,version);
- }
-
- // default implementation
- template<class Archive>
- void serialize(Archive &ar, const unsigned int version)
- {
- typedef typename
- boost::serialization::use_array_optimization<Archive>::template apply<
- typename remove_const< T >::type
- >::type use_optimized;
- serialize_optimized(ar,version,use_optimized());
- }
-
- T * address() const
- {
- return m_t;
- }
-
- std::size_t count() const
- {
- return m_element_count;
- }
-
-private:
- T * const m_t;
- const std::size_t m_element_count;
-};
-
-template<class T, class S>
-inline
-const array_wrapper< T > make_array( T* t, S s){
- const array_wrapper< T > a(t, s);
- return a;
-}
-
-} } // end namespace boost::serialization
-
-// I can't figure out why BOOST_NO_CXX11_HDR_ARRAY
-// has been set for clang-11. So just make sure
-// it's reset now. Needs further research!!!
-
-#if defined(_LIBCPP_VERSION)
-#undef BOOST_NO_CXX11_HDR_ARRAY
-#endif
-
-#ifndef BOOST_NO_CXX11_HDR_ARRAY
-#include <array>
-namespace boost { namespace serialization {
-// implement serialization for std::array
template <class Archive, class T, std::size_t N>
void serialize(Archive& ar, std::array<T,N>& a, const unsigned int /* version */)
{
@@ -146,27 +40,7 @@ void serialize(Archive& ar, std::array<T,N>& a, const unsigned int /* version */
}
} } // end namespace boost::serialization
-#endif
-
-#include <boost/array.hpp>
-
-namespace boost { namespace serialization {
-// implement serialization for boost::array
-template <class Archive, class T, std::size_t N>
-void serialize(Archive& ar, boost::array<T,N>& a, const unsigned int /* version */)
-{
- ar & boost::serialization::make_nvp("elems", a.elems);
-}
-
-} } // end namespace boost::serialization
-#define BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(Archive) \
-namespace boost { namespace serialization { \
-template <> struct use_array_optimization<Archive> { \
- template <class ValueType> \
- struct apply : boost::mpl::apply1<Archive::use_array_optimization \
- , typename boost::remove_const<ValueType>::type \
- >::type {}; \
-}; }}
+#endif // BOOST_NO_CXX11_HDR_ARRAY
#endif //BOOST_SERIALIZATION_ARRAY_HPP
diff --git a/boost/serialization/array_optimization.hpp b/boost/serialization/array_optimization.hpp
new file mode 100644
index 0000000000..40dffba871
--- /dev/null
+++ b/boost/serialization/array_optimization.hpp
@@ -0,0 +1,37 @@
+#ifndef BOOST_SERIALIZATION_ARRAY_OPTIMIZATON_HPP
+#define BOOST_SERIALIZATION_ARRAY_OPTIMIZATON_HPP
+
+// (C) Copyright 2005 Matthias Troyer and Dave Abrahams
+// Use, modification and distribution is subject to the 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/config.hpp> // msvc 6.0 needs this for warning suppression
+
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{
+ using ::size_t;
+} // namespace std
+#endif
+
+#include <boost/mpl/always.hpp>
+#include <boost/mpl/apply.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+namespace boost { namespace serialization {
+
+template <class Archive>
+struct use_array_optimization : boost::mpl::always<boost::mpl::false_> {};
+
+} } // end namespace boost::serialization
+
+#define BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(Archive) \
+namespace boost { namespace serialization { \
+template <> struct use_array_optimization<Archive> { \
+ template <class ValueType> \
+ struct apply : boost::mpl::apply1<Archive::use_array_optimization \
+ , typename boost::remove_const<ValueType>::type \
+ >::type {}; \
+}; }}
+
+#endif //BOOST_SERIALIZATION_ARRAY_OPTIMIZATON_HPP
diff --git a/boost/serialization/array_wrapper.hpp b/boost/serialization/array_wrapper.hpp
new file mode 100644
index 0000000000..adf436e15b
--- /dev/null
+++ b/boost/serialization/array_wrapper.hpp
@@ -0,0 +1,121 @@
+#ifndef BOOST_SERIALIZATION_ARRAY_WRAPPER_HPP
+#define BOOST_SERIALIZATION_ARRAY_WRAPPER_HPP
+
+// (C) Copyright 2005 Matthias Troyer and Dave Abrahams
+// Use, modification and distribution is subject to the 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>
+
+#include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
+
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{
+ using ::size_t;
+} // namespace std
+#endif
+
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/split_member.hpp>
+#include <boost/serialization/wrapper.hpp>
+#include <boost/serialization/collection_size_type.hpp>
+#include <boost/serialization/array_optimization.hpp>
+#include <boost/mpl/always.hpp>
+#include <boost/mpl/apply.hpp>
+#include <boost/mpl/bool_fwd.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+namespace boost { namespace serialization {
+
+template<class T>
+class array_wrapper :
+ public wrapper_traits<const array_wrapper< T > >
+{
+private:
+ array_wrapper & operator=(const array_wrapper & rhs);
+ // note: I would like to make the copy constructor private but this breaks
+ // make_array. So I make make_array a friend
+ template<class Tx, class S>
+ friend const boost::serialization::array_wrapper<Tx> make_array(Tx * t, S s);
+public:
+
+ array_wrapper(const array_wrapper & rhs) :
+ m_t(rhs.m_t),
+ m_element_count(rhs.m_element_count)
+ {}
+public:
+ array_wrapper(T * t, std::size_t s) :
+ m_t(t),
+ m_element_count(s)
+ {}
+
+ // default implementation
+ template<class Archive>
+ void serialize_optimized(Archive &ar, const unsigned int, mpl::false_ ) const
+ {
+ // default implemention does the loop
+ std::size_t c = count();
+ T * t = address();
+ while(0 < c--)
+ ar & boost::serialization::make_nvp("item", *t++);
+ }
+
+ // optimized implementation
+ template<class Archive>
+ void serialize_optimized(Archive &ar, const unsigned int version, mpl::true_ )
+ {
+ boost::serialization::split_member(ar, *this, version);
+ }
+
+ // default implementation
+ template<class Archive>
+ void save(Archive &ar, const unsigned int version) const
+ {
+ ar.save_array(*this,version);
+ }
+
+ // default implementation
+ template<class Archive>
+ void load(Archive &ar, const unsigned int version)
+ {
+ ar.load_array(*this,version);
+ }
+
+ // default implementation
+ template<class Archive>
+ void serialize(Archive &ar, const unsigned int version)
+ {
+ typedef typename
+ boost::serialization::use_array_optimization<Archive>::template apply<
+ typename remove_const< T >::type
+ >::type use_optimized;
+ serialize_optimized(ar,version,use_optimized());
+ }
+
+ T * address() const
+ {
+ return m_t;
+ }
+
+ std::size_t count() const
+ {
+ return m_element_count;
+ }
+
+private:
+ T * const m_t;
+ const std::size_t m_element_count;
+};
+
+template<class T, class S>
+inline
+const array_wrapper< T > make_array(T* t, S s){
+ const array_wrapper< T > a(t, s);
+ return a;
+}
+
+} } // end namespace boost::serialization
+
+
+#endif //BOOST_SERIALIZATION_ARRAY_WRAPPER_HPP
diff --git a/boost/serialization/boost_array.hpp b/boost/serialization/boost_array.hpp
new file mode 100644
index 0000000000..d564ff15de
--- /dev/null
+++ b/boost/serialization/boost_array.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_SERIALIZATION_ARRAY_HPP
+#define BOOST_SERIALIZATION_ARRAY_HPP
+
+// (C) Copyright 2005 Matthias Troyer and Dave Abrahams
+// Use, modification and distribution is subject to the 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>
+
+#include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
+
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{
+ using ::size_t;
+} // namespace std
+#endif
+
+#include <boost/serialization/nvp.hpp>
+#include <boost/array.hpp>
+
+namespace boost { namespace serialization {
+// implement serialization for boost::array
+template <class Archive, class T, std::size_t N>
+void serialize(Archive& ar, boost::array<T,N>& a, const unsigned int /* version */)
+{
+ ar & boost::serialization::make_nvp("elems", a.elems);
+}
+
+} } // end namespace boost::serialization
+
+
+#endif //BOOST_SERIALIZATION_ARRAY_HPP
diff --git a/boost/serialization/collections_load_imp.hpp b/boost/serialization/collections_load_imp.hpp
index 93d64d72b9..c3b165a837 100644
--- a/boost/serialization/collections_load_imp.hpp
+++ b/boost/serialization/collections_load_imp.hpp
@@ -40,6 +40,7 @@ namespace std{
#include <boost/serialization/item_version_type.hpp>
#include <boost/serialization/detail/is_default_constructible.hpp>
#include <boost/utility/enable_if.hpp>
+#include <boost/move/utility_core.hpp>
namespace boost{
namespace serialization {
@@ -93,7 +94,7 @@ collection_load_impl(
while(count-- > 0){
detail::stack_construct<Archive, typename T::value_type> u(ar, item_version);
ar >> boost::serialization::make_nvp("item", u.reference());
- t.push_back(u.reference());
+ t.push_back(boost::move(u.reference()));
ar.reset_object_address(& t.back() , & u.reference());
}
}
diff --git a/boost/serialization/deque.hpp b/boost/serialization/deque.hpp
index 4d0a21f55c..bba81364ce 100644
--- a/boost/serialization/deque.hpp
+++ b/boost/serialization/deque.hpp
@@ -24,7 +24,6 @@
#include <boost/serialization/collections_save_imp.hpp>
#include <boost/serialization/collections_load_imp.hpp>
-#include <boost/serialization/detail/stack_constructor.hpp>
#include <boost/serialization/split_free.hpp>
namespace boost {
diff --git a/boost/serialization/detail/get_data.hpp b/boost/serialization/detail/get_data.hpp
deleted file mode 100644
index 37da7fc3c4..0000000000
--- a/boost/serialization/detail/get_data.hpp
+++ /dev/null
@@ -1,59 +0,0 @@
-// (C) Copyright 2005 Matthias Troyer
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// See http://www.boost.org for updates, documentation, and revision history.
-
-#ifndef BOOST_SERIALIZATION_DETAIL_GET_DATA_HPP
-#define BOOST_SERIALIZATION_DETAIL_GET_DATA_HPP
-
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER)
-# pragma once
-#endif
-
-#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
-#define STD _STLP_STD
-#else
-#define STD std
-#endif
-
-#include <vector>
-#include <valarray>
-
-namespace boost {
-namespace serialization {
-namespace detail {
-
-template <class T, class Allocator>
-T* get_data(STD::vector<T,Allocator>& v)
-{
- return v.empty() ? 0 : &(v[0]);
-}
-
-template <class T, class Allocator>
-T* get_data(STD::vector<T,Allocator> const & v)
-{
- return get_data(const_cast<STD::vector<T,Allocator>&>(v));
-}
-
-template <class T>
-T* get_data(STD::valarray<T>& v)
-{
- return v.size()==0 ? 0 : &(v[0]);
-}
-
-template <class T>
-const T* get_data(STD::valarray<T> const& v)
-{
- return get_data(const_cast<STD::valarray<T>&>(v));
-}
-
-} // detail
-} // serialization
-} // boost
-
-#undef STD
-
-#endif // BOOST_SERIALIZATION_DETAIL_GET_DATA_HPP
diff --git a/boost/serialization/detail/stack_constructor.hpp b/boost/serialization/detail/stack_constructor.hpp
index 806b8877d7..ae14832c6d 100644
--- a/boost/serialization/detail/stack_constructor.hpp
+++ b/boost/serialization/detail/stack_constructor.hpp
@@ -1,5 +1,5 @@
-#ifndef BOOST_SERIALIZATION_DETAIL_STACH_CONSTRUCTOR_HPP
-#define BOOST_SERIALIZATION_DETAIL_STACH_CONSTRUCTOR_HPP
+#ifndef BOOST_SERIALIZATION_DETAIL_STACK_CONSTRUCTOR_HPP
+#define BOOST_SERIALIZATION_DETAIL_STACK_CONSTRUCTOR_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
diff --git a/boost/serialization/ephemeral.hpp b/boost/serialization/ephemeral.hpp
index 09e5016124..3a422c30a3 100644
--- a/boost/serialization/ephemeral.hpp
+++ b/boost/serialization/ephemeral.hpp
@@ -2,7 +2,6 @@
#define BOOST_SERIALIZATION_EPHEMERAL_HPP
// MS compatible compilers support
-#pragma once
#if defined(_MSC_VER)
# pragma once
#endif
diff --git a/boost/serialization/factory.hpp b/boost/serialization/factory.hpp
index 916d75d7dd..db5b1a9226 100644
--- a/boost/serialization/factory.hpp
+++ b/boost/serialization/factory.hpp
@@ -21,6 +21,7 @@
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/comparison/greater.hpp>
+#include <boost/assert.hpp>
namespace std{
#if defined(__LIBCOMO__)
diff --git a/boost/serialization/forward_list.hpp b/boost/serialization/forward_list.hpp
index e17405383c..b8a3c20a6e 100644
--- a/boost/serialization/forward_list.hpp
+++ b/boost/serialization/forward_list.hpp
@@ -16,14 +16,11 @@
// See http://www.boost.org for updates, documentation, and revision history.
+#include <boost/config.hpp>
+
#include <forward_list>
#include <iterator> // distance
-#include <boost/config.hpp>
-#ifdef BOOST_NO_CXX11_HDR_FORWARD_LIST
-#error "not supported for versions earlier than c++11
-#endif
-
#include <boost/serialization/collections_save_imp.hpp>
#include <boost/serialization/collections_load_imp.hpp>
#include <boost/archive/detail/basic_iarchive.hpp>
@@ -33,6 +30,7 @@
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/detail/stack_constructor.hpp>
#include <boost/serialization/detail/is_default_constructible.hpp>
+#include <boost/move/utility_core.hpp>
namespace boost {
namespace serialization {
@@ -72,14 +70,14 @@ collection_load_impl(
t.clear();
boost::serialization::detail::stack_construct<Archive, T> u(ar, item_version);
ar >> boost::serialization::make_nvp("item", u.reference());
- t.emplace_front(u.reference());
+ t.push_front(boost::move(u.reference()));
typename std::forward_list<T, Allocator>::iterator last;
last = t.begin();
ar.reset_object_address(&(*t.begin()) , & u.reference());
while(--count > 0){
detail::stack_construct<Archive, T> u(ar, item_version);
ar >> boost::serialization::make_nvp("item", u.reference());
- last = t.emplace_after(last, u.reference());
+ last = t.insert_after(last, boost::move(u.reference()));
ar.reset_object_address(&(*last) , & u.reference());
}
}
diff --git a/boost/serialization/hash_map.hpp b/boost/serialization/hash_map.hpp
index 615ace8d8a..22626db683 100644
--- a/boost/serialization/hash_map.hpp
+++ b/boost/serialization/hash_map.hpp
@@ -25,6 +25,7 @@
#include <boost/serialization/hash_collections_save_imp.hpp>
#include <boost/serialization/hash_collections_load_imp.hpp>
#include <boost/serialization/split_free.hpp>
+#include <boost/move/utility_core.hpp>
namespace boost {
namespace serialization {
@@ -45,7 +46,7 @@ struct archive_input_hash_map
// borland fails silently w/o full namespace
ar >> boost::serialization::make_nvp("item", t.reference());
std::pair<typename Container::const_iterator, bool> result =
- s.insert(t.reference());
+ s.insert(boost::move(t.reference()));
// note: the following presumes that the map::value_type was NOT tracked
// in the archive. This is the usual case, but here there is no way
// to determine that.
@@ -72,7 +73,7 @@ struct archive_input_hash_multimap
// borland fails silently w/o full namespace
ar >> boost::serialization::make_nvp("item", t.reference());
typename Container::const_iterator result
- = s.insert(t.reference());
+ = s.insert(boost::move(t.reference()));
// note: the following presumes that the map::value_type was NOT tracked
// in the archive. This is the usual case, but here there is no way
// to determine that.
diff --git a/boost/serialization/hash_set.hpp b/boost/serialization/hash_set.hpp
index 6275e0309e..0c72c18457 100644
--- a/boost/serialization/hash_set.hpp
+++ b/boost/serialization/hash_set.hpp
@@ -23,6 +23,7 @@
#include <boost/serialization/hash_collections_save_imp.hpp>
#include <boost/serialization/hash_collections_load_imp.hpp>
#include <boost/serialization/split_free.hpp>
+#include <boost/move/utility_core.hpp>
namespace boost {
namespace serialization {
@@ -43,7 +44,7 @@ struct archive_input_hash_set
// borland fails silently w/o full namespace
ar >> boost::serialization::make_nvp("item", t.reference());
std::pair<typename Container::const_iterator, bool> result =
- s.insert(t.reference());
+ s.insert(boost::move(t.reference()));
if(result.second)
ar.reset_object_address(& (* result.first), & t.reference());
}
@@ -63,7 +64,7 @@ struct archive_input_hash_multiset
// borland fails silently w/o full namespace
ar >> boost::serialization::make_nvp("item", t.reference());
typename Container::const_iterator result
- = s.insert(t.reference());
+ = s.insert(boost::move(t.reference()));
ar.reset_object_address(& (* result), & t.reference());
}
};
diff --git a/boost/serialization/list.hpp b/boost/serialization/list.hpp
index 741dbbe73e..5fdc114d7e 100644
--- a/boost/serialization/list.hpp
+++ b/boost/serialization/list.hpp
@@ -29,7 +29,6 @@
#include <boost/serialization/collection_size_type.hpp>
#include <boost/serialization/item_version_type.hpp>
#include <boost/serialization/split_free.hpp>
-#include <boost/serialization/detail/stack_constructor.hpp>
namespace boost {
namespace serialization {
diff --git a/boost/serialization/map.hpp b/boost/serialization/map.hpp
index 2582f9aced..9209864c8c 100644
--- a/boost/serialization/map.hpp
+++ b/boost/serialization/map.hpp
@@ -31,6 +31,7 @@
#include <boost/serialization/utility.hpp>
#include <boost/serialization/collections_save_imp.hpp>
#include <boost/serialization/split_free.hpp>
+#include <boost/move/utility_core.hpp>
namespace boost {
namespace serialization {
@@ -59,11 +60,7 @@ inline void load_map_collection(Archive & ar, Container &s)
detail::stack_construct<Archive, type> t(ar, item_version);
ar >> boost::serialization::make_nvp("item", t.reference());
typename Container::iterator result =
- #ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP
- s.insert(hint, t.reference());
- #else
- s.emplace_hint(hint, t.reference());
- #endif
+ s.insert(hint, boost::move(t.reference()));
ar.reset_object_address(& (result->second), & t.reference().second);
hint = result;
++hint;
diff --git a/boost/serialization/optional.hpp b/boost/serialization/optional.hpp
index 4024cf5e61..ecd1756d50 100644
--- a/boost/serialization/optional.hpp
+++ b/boost/serialization/optional.hpp
@@ -19,12 +19,16 @@
#include <boost/archive/detail/basic_iarchive.hpp>
#include <boost/optional.hpp>
+#include <boost/move/utility_core.hpp>
+
#include <boost/serialization/item_version_type.hpp>
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/level.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/version.hpp>
+#include <boost/type_traits/is_pointer.hpp>
#include <boost/serialization/detail/stack_constructor.hpp>
+#include <boost/serialization/detail/is_default_constructible.hpp>
// function specializations must be defined in the appropriate
// namespace - boost::serialization
@@ -37,6 +41,15 @@ void save(
const boost::optional< T > & t,
const unsigned int /*version*/
){
+ // It is an inherent limitation to the serialization of optional.hpp
+ // that the underlying type must be either a pointer or must have a
+ // 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
+ );
const bool tflag = t.is_initialized();
ar << boost::serialization::make_nvp("initialized", tflag);
if (tflag){
@@ -63,22 +76,25 @@ void load(
){
bool tflag;
ar >> boost::serialization::make_nvp("initialized", tflag);
- if (tflag){
- 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){
- // item_version is handled as an attribute so it doesnt need an NVP
- ar >> BOOST_SERIALIZATION_NVP(item_version);
- }
- detail::stack_construct<Archive, T> aux(ar, item_version);
- ar >> boost::serialization::make_nvp("value", aux.reference());
- t.reset(aux.reference());
- }
- else {
+ if(! tflag){
t.reset();
+ 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);
}
+ 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()
+ );
}
template<class Archive, class T>
diff --git a/boost/serialization/priority_queue.hpp b/boost/serialization/priority_queue.hpp
index 3ba63a5b2d..5b08ffd1e8 100644
--- a/boost/serialization/priority_queue.hpp
+++ b/boost/serialization/priority_queue.hpp
@@ -18,6 +18,8 @@
#include <queue>
#include <boost/config.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
// function specializations must be defined in the appropriate
// namespace - boost::serialization
diff --git a/boost/serialization/queue.hpp b/boost/serialization/queue.hpp
index 58e1ee92f4..b22745215d 100644
--- a/boost/serialization/queue.hpp
+++ b/boost/serialization/queue.hpp
@@ -18,6 +18,8 @@
#include <queue>
#include <boost/config.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
// function specializations must be defined in the appropriate
// namespace - boost::serialization
diff --git a/boost/serialization/set.hpp b/boost/serialization/set.hpp
index 6b957d470e..643906c5aa 100644
--- a/boost/serialization/set.hpp
+++ b/boost/serialization/set.hpp
@@ -29,6 +29,7 @@
#include <boost/serialization/collections_save_imp.hpp>
#include <boost/serialization/split_free.hpp>
+#include <boost/move/utility_core.hpp>
namespace boost {
namespace serialization {
@@ -55,11 +56,7 @@ inline void load_set_collection(Archive & ar, Container &s)
// borland fails silently w/o full namespace
ar >> boost::serialization::make_nvp("item", t.reference());
typename Container::iterator result =
- #ifdef BOOST_NO_CXX11_HDR_UNORDERED_SET
- s.insert(hint, t.reference());
- #else
- s.emplace_hint(hint, t.reference());
- #endif
+ s.insert(hint, boost::move(t.reference()));
ar.reset_object_address(& (* result), & t.reference());
hint = result;
}
diff --git a/boost/serialization/shared_ptr_helper.hpp b/boost/serialization/shared_ptr_helper.hpp
index 189447a804..37c34d6b2c 100644
--- a/boost/serialization/shared_ptr_helper.hpp
+++ b/boost/serialization/shared_ptr_helper.hpp
@@ -31,9 +31,6 @@
#include <boost/serialization/throw_exception.hpp>
#include <boost/serialization/type_info_implementation.hpp>
#include <boost/archive/archive_exception.hpp>
-#include <boost/archive/detail/decl.hpp>
-
-#include <boost/archive/detail/abi_prefix.hpp> // must be the last headern
namespace boost_132 {
template<class T> class shared_ptr;
@@ -94,7 +91,7 @@ public:
// by a change in load_construct_data below. It makes this file suitable
// only for loading pointers into a 1.33 or later boost system.
std::list<boost_132::shared_ptr<const void> > * m_pointers_132;
- BOOST_ARCHIVE_DECL void
+ void
append(const boost_132::shared_ptr<const void> & t){
if(NULL == m_pointers_132)
m_pointers_132 = new std::list<boost_132::shared_ptr<const void> >;
@@ -209,6 +206,4 @@ public:
} // namespace serialization
} // namespace boost
-#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
-
#endif // BOOST_SERIALIZATION_SHARED_PTR_HELPER_HPP
diff --git a/boost/serialization/singleton.hpp b/boost/serialization/singleton.hpp
index fcb79c3694..a40488c6df 100644
--- a/boost/serialization/singleton.hpp
+++ b/boost/serialization/singleton.hpp
@@ -85,11 +85,19 @@ class BOOST_SYMBOL_VISIBLE singleton_module :
public boost::noncopyable
{
private:
- static bool & get_lock();
+ BOOST_SERIALIZATION_DECL static bool & get_lock();
public:
- BOOST_SERIALIZATION_DECL static void lock();
- BOOST_SERIALIZATION_DECL static void unlock();
- BOOST_SERIALIZATION_DECL static bool is_locked();
+ static void lock(){
+ get_lock() = true;
+ }
+
+ static void unlock(){
+ get_lock() = false;
+ }
+
+ static bool is_locked(){
+ return get_lock();
+ }
};
#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
@@ -111,6 +119,12 @@ 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
{
diff --git a/boost/serialization/slist.hpp b/boost/serialization/slist.hpp
index af300683e0..d9b971bc4f 100644
--- a/boost/serialization/slist.hpp
+++ b/boost/serialization/slist.hpp
@@ -29,6 +29,7 @@
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/detail/stack_constructor.hpp>
#include <boost/serialization/detail/is_default_constructible.hpp>
+#include <boost/move/utility_core.hpp>
namespace boost {
namespace serialization {
@@ -67,14 +68,14 @@ collection_load_impl(
t.clear();
boost::serialization::detail::stack_construct<Archive, T> u(ar, item_version);
ar >> boost::serialization::make_nvp("item", u.reference());
- t.push_front(u.reference());
+ t.push_front(boost::move(u.reference()));
typename BOOST_STD_EXTENSION_NAMESPACE::slist<T, Allocator>::iterator last;
last = t.begin();
ar.reset_object_address(&(*t.begin()) , & u.reference());
while(--count > 0){
detail::stack_construct<Archive, T> u(ar, item_version);
ar >> boost::serialization::make_nvp("item", u.reference());
- last = t.insert_after(last, u.reference());
+ last = t.insert_after(last, boost::move(u.reference()));
ar.reset_object_address(&(*last) , & u.reference());
}
}
@@ -109,14 +110,14 @@ inline void load(
t.clear();
boost::serialization::detail::stack_construct<Archive, U> u(ar, item_version);
ar >> boost::serialization::make_nvp("item", u.reference());
- t.push_front(u.reference());
+ t.push_front(boost::move(u.reference()));
typename BOOST_STD_EXTENSION_NAMESPACE::slist<U, Allocator>::iterator last;
last = t.begin();
ar.reset_object_address(&(*t.begin()) , & u.reference());
while(--count > 0){
detail::stack_construct<Archive, U> u(ar, item_version);
ar >> boost::serialization::make_nvp("item", u.reference());
- last = t.insert_after(last, u.reference());
+ last = t.insert_after(last, boost::move(u.reference()));
ar.reset_object_address(&(*last) , & u.reference());
}
}
diff --git a/boost/serialization/stack.hpp b/boost/serialization/stack.hpp
index aea3ba8e00..96f90fe876 100644
--- a/boost/serialization/stack.hpp
+++ b/boost/serialization/stack.hpp
@@ -18,6 +18,8 @@
#include <stack>
#include <boost/config.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
// function specializations must be defined in the appropriate
// namespace - boost::serialization
diff --git a/boost/serialization/strong_typedef.hpp b/boost/serialization/strong_typedef.hpp
index c1bf1844bf..fdd1b24c9c 100644
--- a/boost/serialization/strong_typedef.hpp
+++ b/boost/serialization/strong_typedef.hpp
@@ -10,6 +10,7 @@
// strong_typedef.hpp:
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// (C) Copyright 2016 Ashish Sadanandan
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -24,23 +25,26 @@
#include <boost/config.hpp>
#include <boost/operators.hpp>
-
-#define BOOST_STRONG_TYPEDEF(T, D) \
-struct D \
- : boost::totally_ordered1< D \
- , boost::totally_ordered2< D, T \
- > > \
-{ \
- T t; \
- explicit D(const T t_) : t(t_) {}; \
- D(): t() {}; \
- D(const D & t_) : t(t_.t){} \
- D & operator=(const D & rhs) { t = rhs.t; return *this;} \
- D & operator=(const T & rhs) { t = rhs; return *this;} \
- operator const T & () const {return t; } \
- operator T & () { return t; } \
- bool operator==(const D & rhs) const { return t == rhs.t; } \
- bool operator<(const D & rhs) const { return t < rhs.t; } \
+#include <boost/type_traits/has_nothrow_assign.hpp>
+#include <boost/type_traits/has_nothrow_constructor.hpp>
+#include <boost/type_traits/has_nothrow_copy.hpp>
+
+#define BOOST_STRONG_TYPEDEF(T, D) \
+struct D \
+ : boost::totally_ordered1< D \
+ , boost::totally_ordered2< D, T \
+ > > \
+{ \
+ T t; \
+ explicit D(const T& t_) BOOST_NOEXCEPT_IF(boost::has_nothrow_copy_constructor<T>::value) : t(t_) {} \
+ D() BOOST_NOEXCEPT_IF(boost::has_nothrow_default_constructor<T>::value) : t() {} \
+ D(const D & t_) BOOST_NOEXCEPT_IF(boost::has_nothrow_copy_constructor<T>::value) : t(t_.t) {} \
+ D& operator=(const D& rhs) BOOST_NOEXCEPT_IF(boost::has_nothrow_assign<T>::value) {t = rhs.t; return *this;} \
+ D& operator=(const T& rhs) BOOST_NOEXCEPT_IF(boost::has_nothrow_assign<T>::value) {t = rhs; return *this;} \
+ operator const T&() const {return t;} \
+ operator T&() {return t;} \
+ bool operator==(const D& rhs) const {return t == rhs.t;} \
+ bool operator<(const D& rhs) const {return t < rhs.t;} \
};
#endif // BOOST_SERIALIZATION_STRONG_TYPEDEF_HPP
diff --git a/boost/serialization/unordered_collections_load_imp.hpp b/boost/serialization/unordered_collections_load_imp.hpp
index 48c568d633..d56a423d18 100644
--- a/boost/serialization/unordered_collections_load_imp.hpp
+++ b/boost/serialization/unordered_collections_load_imp.hpp
@@ -33,7 +33,6 @@ namespace std{
#include <boost/archive/detail/basic_iarchive.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/nvp.hpp>
-#include <boost/serialization/detail/stack_constructor.hpp>
#include <boost/serialization/collection_size_type.hpp>
#include <boost/serialization/item_version_type.hpp>
diff --git a/boost/serialization/valarray.hpp b/boost/serialization/valarray.hpp
index efe102f6cf..9eece5c173 100644
--- a/boost/serialization/valarray.hpp
+++ b/boost/serialization/valarray.hpp
@@ -18,10 +18,12 @@
#include <valarray>
#include <boost/config.hpp>
+
+#include <boost/serialization/collections_save_imp.hpp>
+#include <boost/serialization/collections_load_imp.hpp>
#include <boost/serialization/split_free.hpp>
-#include <boost/serialization/array.hpp>
#include <boost/serialization/collection_size_type.hpp>
-#include <boost/serialization/detail/get_data.hpp>
+#include <boost/serialization/array_wrapper.hpp>
// function specializations must be defined in the appropriate
// namespace - boost::serialization
@@ -42,8 +44,13 @@ void save( Archive & ar, const STD::valarray<U> &t, const unsigned int /*file_ve
{
const collection_size_type count(t.size());
ar << BOOST_SERIALIZATION_NVP(count);
- if (t.size())
- ar << make_array(detail::get_data(t), t.size());
+ if (t.size()){
+ // explict template arguments to pass intel C++ compiler
+ ar << serialization::make_array<const U, collection_size_type>(
+ static_cast<const U *>(&t[0]),
+ count
+ );
+ }
}
template<class Archive, class U>
@@ -52,8 +59,13 @@ void load( Archive & ar, STD::valarray<U> &t, const unsigned int /*file_version
collection_size_type count;
ar >> BOOST_SERIALIZATION_NVP(count);
t.resize(count);
- if (t.size())
- ar >> make_array(detail::get_data(t), t.size());
+ if (t.size()){
+ // explict template arguments to pass intel C++ compiler
+ ar >> serialization::make_array<U, collection_size_type>(
+ static_cast<U *>(&t[0]),
+ count
+ );
+ }
}
// split non-intrusive serialization function member into separate
diff --git a/boost/serialization/vector.hpp b/boost/serialization/vector.hpp
index a1737548ef..9a114c00e2 100644
--- a/boost/serialization/vector.hpp
+++ b/boost/serialization/vector.hpp
@@ -31,9 +31,7 @@
#include <boost/serialization/collections_save_imp.hpp>
#include <boost/serialization/collections_load_imp.hpp>
#include <boost/serialization/split_free.hpp>
-#include <boost/serialization/array.hpp>
-#include <boost/serialization/detail/get_data.hpp>
-#include <boost/serialization/detail/stack_constructor.hpp>
+#include <boost/serialization/array_wrapper.hpp>
#include <boost/mpl/bool_fwd.hpp>
#include <boost/mpl/if.hpp>
@@ -103,7 +101,11 @@ inline void save(
const collection_size_type count(t.size());
ar << BOOST_SERIALIZATION_NVP(count);
if (!t.empty())
- ar << boost::serialization::make_array(detail::get_data(t),t.size());
+ // explict template arguments to pass intel C++ compiler
+ ar << serialization::make_array<const U, collection_size_type>(
+ static_cast<const U *>(&t[0]),
+ count
+ );
}
template<class Archive, class U, class Allocator>
@@ -121,7 +123,11 @@ inline void load(
ar >> BOOST_SERIALIZATION_NVP(item_version);
}
if (!t.empty())
- ar >> boost::serialization::make_array(detail::get_data(t),t.size());
+ // explict template arguments to pass intel C++ compiler
+ ar >> serialization::make_array<U, collection_size_type>(
+ static_cast<U *>(&t[0]),
+ count
+ );
}
// dispatch to either default or optimized versions
diff --git a/boost/signals2/deconstruct.hpp b/boost/signals2/deconstruct.hpp
index 462fa1d21f..dd78d921ee 100644
--- a/boost/signals2/deconstruct.hpp
+++ b/boost/signals2/deconstruct.hpp
@@ -64,7 +64,7 @@ public:
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<class... Args>
- const shared_ptr<T>& postconstruct(Args && ... args)
+ const shared_ptr<T>& postconstruct(Args && ... args) const
{
if(!_postconstructed)
{
diff --git a/boost/signals2/detail/auto_buffer.hpp b/boost/signals2/detail/auto_buffer.hpp
index 0970d3da90..4c55a751ae 100644
--- a/boost/signals2/detail/auto_buffer.hpp
+++ b/boost/signals2/detail/auto_buffer.hpp
@@ -971,7 +971,7 @@ namespace detail
pointer uninitialized_grow( size_type n ) // strong
{
- if( size_ + n <= members_.capacity_ )
+ if( size_ + n > members_.capacity_ )
reserve( size_ + n );
pointer res = end();
@@ -1116,7 +1116,7 @@ namespace detail
inline bool operator<=( const auto_buffer<T,SBP,GP,A>& l,
const auto_buffer<T,SBP,GP,A>& r )
{
- return !(r > l);
+ return !(l > r);
}
template< class T, class SBP, class GP, class A >
diff --git a/boost/signals2/detail/signal_template.hpp b/boost/signals2/detail/signal_template.hpp
index 036876727a..b92a143ade 100644
--- a/boost/signals2/detail/signal_template.hpp
+++ b/boost/signals2/detail/signal_template.hpp
@@ -599,7 +599,6 @@ namespace boost
class BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION: public signal_base,
public detail::BOOST_SIGNALS2_STD_FUNCTIONAL_BASE
- (typename detail::result_type_wrapper<typename Combiner::result_type>::type)
{
typedef detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
<BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> impl_class;
diff --git a/boost/signals2/detail/signals_common_macros.hpp b/boost/signals2/detail/signals_common_macros.hpp
index 4ca4403827..acc0936281 100644
--- a/boost/signals2/detail/signals_common_macros.hpp
+++ b/boost/signals2/detail/signals_common_macros.hpp
@@ -137,7 +137,7 @@
#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(arity) BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(arity)
#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION
-#define BOOST_SIGNALS2_STD_FUNCTIONAL_BASE(result_type) std_functional_base
+#define BOOST_SIGNALS2_STD_FUNCTIONAL_BASE std_functional_base
#define BOOST_SIGNALS2_PP_COMMA_IF(arity) BOOST_PP_COMMA_IF(arity)
@@ -205,8 +205,8 @@
ExtendedSlotFunction, \
Mutex>
-#define BOOST_SIGNALS2_STD_FUNCTIONAL_BASE(result_type) \
- std_functional_base<result_type , Args...>
+#define BOOST_SIGNALS2_STD_FUNCTIONAL_BASE \
+ std_functional_base<Args...>
#define BOOST_SIGNALS2_PP_COMMA_IF(arity) ,
diff --git a/boost/signals2/detail/slot_template.hpp b/boost/signals2/detail/slot_template.hpp
index fc19f5139c..1c17c5b76a 100644
--- a/boost/signals2/detail/slot_template.hpp
+++ b/boost/signals2/detail/slot_template.hpp
@@ -35,7 +35,7 @@ namespace boost
template<BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
class BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION
- : public slot_base, public detail::BOOST_SIGNALS2_STD_FUNCTIONAL_BASE(R)
+ : public slot_base, public detail::BOOST_SIGNALS2_STD_FUNCTIONAL_BASE
{
public:
diff --git a/boost/signals2/detail/variadic_arg_type.hpp b/boost/signals2/detail/variadic_arg_type.hpp
index 14d54b2e3e..6079c16332 100644
--- a/boost/signals2/detail/variadic_arg_type.hpp
+++ b/boost/signals2/detail/variadic_arg_type.hpp
@@ -32,15 +32,20 @@ namespace boost
typedef typename variadic_arg_type<n - 1, Args...>::type type;
};
- template <typename R, typename ... Args>
+ template <typename ... Args>
struct std_functional_base
{};
- template <typename R, typename T1>
- struct std_functional_base<R, T1>: public std::unary_function<T1, R>
- {};
- template <typename R, typename T1, typename T2>
- struct std_functional_base<R, T1, T2>: public std::binary_function<T1, T2, R>
- {};
+ template <typename T1>
+ struct std_functional_base<T1>
+ {
+ typedef T1 argument_type;
+ };
+ template <typename T1, typename T2>
+ struct std_functional_base<T1, T2>
+ {
+ typedef T1 first_argument_type;
+ typedef T2 second_argument_type;
+ };
} // namespace detail
} // namespace signals2
} // namespace boost
diff --git a/boost/smart_ptr/allocate_shared_array.hpp b/boost/smart_ptr/allocate_shared_array.hpp
index 1ae5cc7832..b43b43d575 100644
--- a/boost/smart_ptr/allocate_shared_array.hpp
+++ b/boost/smart_ptr/allocate_shared_array.hpp
@@ -1,181 +1,1026 @@
/*
- * Copyright (c) 2012-2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
+Copyright 2012-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_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
-#include <boost/smart_ptr/detail/array_count_impl.hpp>
-#include <boost/smart_ptr/detail/sp_if_array.hpp>
+#include <boost/smart_ptr/shared_ptr.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 {
- template<class T, class A>
- inline typename boost::detail::sp_if_array<T>::type
- allocate_shared(const A& allocator, std::size_t size) {
- typedef typename boost::detail::array_inner<T>::type T1;
- typedef typename boost::detail::array_base<T1>::type T2;
- typedef boost::detail::ms_init_tag R1;
- typedef boost::detail::as_allocator<A, T, R1> A1;
- typedef boost::detail::ms_in_allocator_tag D1;
- std::size_t n1 = size * boost::detail::array_total<T1>::size;
- T1* p1 = 0;
- T2* p2 = 0;
- D1 d1;
- A1 a1(allocator, size, &p2);
- shared_ptr<T> s1(p1, d1, a1);
- A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
- a2->set(0);
+namespace detail {
+
+template<class>
+struct sp_if_array { };
+
+template<class T>
+struct sp_if_array<T[]> {
+ typedef boost::shared_ptr<T[]> type;
+};
+
+template<class>
+struct sp_if_size_array { };
+
+template<class T, std::size_t N>
+struct sp_if_size_array<T[N]> {
+ typedef boost::shared_ptr<T[N]> type;
+};
+
+template<class>
+struct sp_array_element { };
+
+template<class T>
+struct sp_array_element<T[]> {
+ typedef T type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_element<T[N]> {
+ typedef T type;
+};
+
+template<class T>
+struct sp_array_scalar {
+ typedef T type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_scalar<T[N]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_scalar<const T[N]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_scalar<volatile T[N]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_scalar<const volatile T[N]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_scalar<T[]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_scalar<const T[]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_scalar<volatile T[]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_scalar<const volatile T[]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_count {
+ enum {
+ value = 1
+ };
+};
+
+template<class T, std::size_t N>
+struct sp_array_count<T[N]> {
+ enum {
+ value = N * sp_array_count<T>::value
+ };
+};
+
+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
+ };
+};
+
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- boost::detail::as_init(allocator, p2, n1);
+template<class A, class T>
+struct sp_bind_allocator {
+ typedef typename std::allocator_traits<A>::template
+ rebind_alloc<T> type;
+};
#else
- boost::detail::ms_init(p2, n1);
+template<class A, class T>
+struct sp_bind_allocator {
+ typedef typename A::template rebind<T>::other type;
+};
#endif
- a2->set(p2);
- p1 = reinterpret_cast<T1*>(p2);
- return shared_ptr<T>(s1, p1);
- }
-
- template<class T, class A>
- inline typename boost::detail::sp_if_size_array<T>::type
- allocate_shared(const A& allocator) {
- typedef typename boost::detail::array_inner<T>::type T1;
- typedef typename boost::detail::array_base<T1>::type T2;
- typedef boost::detail::ms_init_tag R1;
- typedef boost::detail::as_allocator<A, T, R1> A1;
- typedef boost::detail::ms_in_allocator_tag D1;
- enum {
- N = boost::detail::array_total<T>::size
- };
- T1* p1 = 0;
- T2* p2 = 0;
- D1 d1;
- A1 a1(allocator, &p2);
- shared_ptr<T> s1(p1, d1, a1);
- A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
- a2->set(0);
+
+template<bool, class = void>
+struct sp_enable { };
+
+template<class T>
+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<class T>
+inline
+typename sp_enable<!boost::has_trivial_destructor<T>::value>::type
+sp_array_destroy(T* storage, std::size_t size)
+{
+ while (size > 0) {
+ storage[--size].~T();
+ }
+}
+
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- boost::detail::as_init(allocator, p2, N);
+template<class A, class T>
+inline void
+sp_array_destroy(A& allocator, T* storage, std::size_t size)
+{
+ while (size > 0) {
+ std::allocator_traits<A>::destroy(allocator, &storage[--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)
+{
+ 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_construct(T* storage, std::size_t size)
+{
+ std::size_t i = 0;
+ try {
+ for (; i < size; ++i) {
+ ::new(static_cast<void*>(storage + i)) T();
+ }
+ } catch (...) {
+ while (i > 0) {
+ storage[--i].~T();
+ }
+ throw;
+ }
+}
+
+template<class T>
+inline void
+sp_array_construct(T* storage, 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]);
+ }
+ } catch (...) {
+ while (i > 0) {
+ storage[--i].~T();
+ }
+ throw;
+ }
+}
#else
- boost::detail::ms_init(p2, N);
+template<class T>
+inline void
+sp_array_construct(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 void
+sp_array_construct(T* storage, 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]);
+ }
+}
#endif
- a2->set(p2);
- p1 = reinterpret_cast<T1*>(p2);
- return shared_ptr<T>(s1, p1);
- }
-
- template<class T, class A>
- inline typename boost::detail::sp_if_array<T>::type
- allocate_shared(const A& allocator, std::size_t size,
- const typename boost::detail::array_inner<T>::type& value) {
- typedef typename boost::detail::array_inner<T>::type T1;
- typedef typename boost::detail::array_base<T1>::type T2;
- typedef const T2 T3;
- typedef boost::detail::ms_init_tag R1;
- typedef boost::detail::as_allocator<A, T, R1> A1;
- typedef boost::detail::ms_in_allocator_tag D1;
- enum {
- M = boost::detail::array_total<T1>::size
- };
- std::size_t n1 = M * size;
- T1* p1 = 0;
- T2* p2 = 0;
- T3* p3 = reinterpret_cast<T3*>(&value);
- D1 d1;
- A1 a1(allocator, size, &p2);
- shared_ptr<T> s1(p1, d1, a1);
- A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
- a2->set(0);
+
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- boost::detail::as_init<T2, A, M>(allocator, p2, n1, p3);
+#if !defined(BOOST_NO_EXCEPTIONS)
+template<class A, class T>
+inline void
+sp_array_construct(A& allocator, T* storage, std::size_t size)
+{
+ std::size_t i = 0;
+ try {
+ for (i = 0; i < size; ++i) {
+ std::allocator_traits<A>::construct(allocator, storage + i);
+ }
+ } catch (...) {
+ sp_array_destroy(allocator, storage, 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)
+{
+ std::size_t i = 0;
+ try {
+ for (i = 0; i < size; ++i) {
+ std::allocator_traits<A>::construct(allocator, storage + i,
+ list[i % count]);
+ }
+ } catch (...) {
+ sp_array_destroy(allocator, storage, i);
+ throw;
+ }
+}
#else
- boost::detail::ms_init<T2, M>(p2, n1, p3);
+template<class A, class T>
+inline void
+sp_array_construct(A& allocator, T* storage, std::size_t size)
+{
+ for (std::size_t i = 0; i < size; ++i) {
+ std::allocator_traits<A>::construct(allocator, storage + 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)
+{
+ for (std::size_t i = 0; i < size; ++i) {
+ std::allocator_traits<A>::construct(allocator, storage + i,
+ list[i % count]);
+ }
+}
+#endif
#endif
- a2->set(p2);
- p1 = reinterpret_cast<T1*>(p2);
- return shared_ptr<T>(s1, p1);
- }
-
- template<class T, class A>
- inline typename boost::detail::sp_if_size_array<T>::type
- allocate_shared(const A& allocator,
- const typename boost::detail::array_inner<T>::type& value) {
- typedef typename boost::detail::array_inner<T>::type T1;
- typedef typename boost::detail::array_base<T1>::type T2;
- typedef const T2 T3;
- typedef boost::detail::ms_init_tag R1;
- typedef boost::detail::as_allocator<A, T, R1> A1;
- typedef boost::detail::ms_in_allocator_tag D1;
- enum {
- N = boost::detail::array_total<T>::size,
- M = boost::detail::array_total<T1>::size
- };
- T1* p1 = 0;
- T2* p2 = 0;
- T3* p3 = reinterpret_cast<T3*>(&value);
- D1 d1;
- A1 a1(allocator, &p2);
- shared_ptr<T> s1(p1, d1, a1);
- A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
- a2->set(0);
+
+template<class T>
+inline
+typename sp_enable<boost::has_trivial_constructor<T>::value>::type
+sp_array_default(T*, std::size_t) BOOST_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)
+{
+ std::size_t i = 0;
+ try {
+ for (; i < size; ++i) {
+ ::new(static_cast<void*>(storage + i)) T;
+ }
+ } catch (...) {
+ while (i > 0) {
+ storage[--i].~T();
+ }
+ 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)
+{
+ for (std::size_t i = 0; i < size; ++i) {
+ ::new(static_cast<void*>(storage + 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)
- boost::detail::as_init<T2, A, M>(allocator, p2, N, p3);
+template<class T, std::size_t N, class A>
+class sp_size_array_destroyer {
+public:
+ template<class U>
+ static void operator_fn(U) BOOST_NOEXCEPT { }
+
+ template<class U>
+ sp_size_array_destroyer(const U& allocator) BOOST_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 {
+ return allocator_;
+ }
+
+ std::size_t size() const BOOST_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;
+
+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) { }
+
+ 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);
+ }
+
+ 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 {
+ return allocator_;
+ }
+
+ std::size_t size() const BOOST_NOEXCEPT {
+ return size_;
+ }
+
+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 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 A, class T>
+struct sp_select_deleter {
+ typedef sp_array_destroyer<T,
+ typename sp_bind_allocator<A, T>::type> type;
+};
+
+template<class U, class T>
+struct sp_select_deleter<std::allocator<U>, T> {
+ typedef sp_array_deleter<T> type;
+};
#else
- boost::detail::ms_init<T2, M>(p2, N, p3);
+template<class, class T, std::size_t N>
+struct sp_select_size_deleter {
+ typedef sp_size_array_deleter<T, N> type;
+};
+
+template<class, class T>
+struct sp_select_deleter {
+ typedef sp_array_deleter<T> type;
+};
+#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;
+
+private:
+ typedef sp_counted_impl_pda<P, deleter_type, A> type;
+ typedef typename sp_bind_allocator<A, type>::type deallocator;
+
+public:
+ sp_counted_impl_pda(P, const deleter_type&, const A& allocator)
+ : deleter_(allocator),
+ allocator_(allocator) { }
+
+ sp_counted_impl_pda(P, const A& allocator)
+ : deleter_(allocator) { }
+
+ void dispose() {
+ deleter_(0);
+ }
+
+ void destroy() {
+ deallocator allocator(allocator_);
+ this->~type();
+ allocator.deallocate(this, 1);
+ }
+
+ void* get_deleter(const sp_typeinfo&) {
+ return &reinterpret_cast<char&>(deleter_);
+ }
+
+ void* get_untyped_deleter() {
+ return &reinterpret_cast<char&>(deleter_);
+ }
+
+private:
+ deleter_type deleter_;
+ A allocator_;
+};
+
+#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;
+
+private:
+ typedef sp_counted_impl_pda<P, deleter_type, A> type;
+ typedef typename sp_bind_allocator<A, type>::type deallocator;
+
+public:
+ sp_counted_impl_pda(P, const deleter_type&, const A& allocator)
+ : deleter_(allocator) { }
+
+ sp_counted_impl_pda(P, const A& allocator)
+ : deleter_(allocator) { }
+
+ void dispose() {
+ deleter_(0);
+ }
+
+ void destroy() {
+ deallocator allocator(deleter_.allocator());
+ this->~type();
+ allocator.deallocate(this, 1);
+ }
+
+ void* get_deleter(const sp_typeinfo&) {
+ return &reinterpret_cast<char&>(deleter_);
+ }
+
+ void* get_untyped_deleter() {
+ return &reinterpret_cast<char&>(deleter_);
+ }
+
+private:
+ deleter_type deleter_;
+};
#endif
- a2->set(p2);
- p1 = reinterpret_cast<T1*>(p2);
- return shared_ptr<T>(s1, p1);
- }
-
- template<class T, class A>
- inline typename boost::detail::sp_if_array<T>::type
- allocate_shared_noinit(const A& allocator, std::size_t size) {
- typedef typename boost::detail::array_inner<T>::type T1;
- typedef typename boost::detail::array_base<T1>::type T2;
- typedef boost::detail::ms_noinit_tag R1;
- typedef boost::detail::as_allocator<A, T, R1> A1;
- typedef boost::detail::ms_in_allocator_tag D1;
- std::size_t n1 = size * boost::detail::array_total<T1>::size;
- T1* p1 = 0;
- T2* p2 = 0;
- D1 d1;
- A1 a1(allocator, size, &p2);
- shared_ptr<T> s1(p1, d1, a1);
- A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
- a2->set(0);
- boost::detail::ms_noinit(p2, n1);
- a2->set(p2);
- p1 = reinterpret_cast<T1*>(p2);
- return shared_ptr<T>(s1, p1);
- }
-
- template<class T, class A>
- inline typename boost::detail::sp_if_size_array<T>::type
- allocate_shared_noinit(const A& allocator) {
- typedef typename boost::detail::array_inner<T>::type T1;
- typedef typename boost::detail::array_base<T1>::type T2;
- typedef boost::detail::ms_noinit_tag R1;
- typedef boost::detail::as_allocator<A, T, R1> A1;
- typedef boost::detail::ms_in_allocator_tag D1;
- enum {
- N = boost::detail::array_total<T>::size
- };
- T1* p1 = 0;
- T2* p2 = 0;
- D1 d1;
- A1 a1(allocator, &p2);
- shared_ptr<T> s1(p1, d1, a1);
- A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
- a2->set(0);
- boost::detail::ms_noinit(p2, N);
- a2->set(p2);
- p1 = reinterpret_cast<T1*>(p2);
- return shared_ptr<T>(s1, p1);
+
+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()) { }
+
+ void dispose() {
+ deleter_(0);
+ }
+
+ void destroy() {
+ deallocator allocator(allocator_, deleter_.size());
+ this->~type();
+ allocator.deallocate(this, 1);
+ }
+
+ void* get_deleter(const sp_typeinfo&) {
+ return &reinterpret_cast<char&>(deleter_);
+ }
+
+ void* get_untyped_deleter() {
+ return &reinterpret_cast<char&>(deleter_);
+ }
+
+private:
+ deleter_type deleter_;
+ A allocator_;
+};
+
+#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;
+
+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);
+ }
+
+ void destroy() {
+ deallocator allocator(deleter_.allocator(), deleter_.size());
+ this->~type();
+ allocator.deallocate(this, 1);
+ }
+
+ void* get_deleter(const sp_typeinfo&) {
+ return &reinterpret_cast<char&>(deleter_);
+ }
+
+ void* get_untyped_deleter() {
+ return &reinterpret_cast<char&>(deleter_);
}
+
+private:
+ deleter_type deleter_;
+};
+#endif
+
+} /* detail */
+
+template<class T, class A>
+inline typename detail::sp_if_size_array<T>::type
+allocate_shared(const A& allocator)
+{
+ 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));
+}
+
+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)
+{
+ 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));
+}
+
+template<class T, class A>
+inline typename detail::sp_if_size_array<T>::type
+allocate_shared_noinit(const A& allocator)
+{
+ 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));
}
+template<class T, class A>
+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_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));
+}
+
+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)
+{
+ 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),
+ reinterpret_cast<const scalar*>(&value),
+ detail::sp_array_count<type>::value);
+ return shared_ptr<T>(result, static_cast<type*>(start));
+}
+
+template<class T, class A>
+inline typename detail::sp_if_array<T>::type
+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 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));
+}
+
+} /* boost */
+
#endif
diff --git a/boost/smart_ptr/detail/array_allocator.hpp b/boost/smart_ptr/detail/array_allocator.hpp
deleted file mode 100644
index 71479967bc..0000000000
--- a/boost/smart_ptr/detail/array_allocator.hpp
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (c) 2012-2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
-#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
-#define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
-
-#include <boost/align/align.hpp>
-#include <boost/smart_ptr/detail/array_traits.hpp>
-#include <boost/smart_ptr/detail/array_utility.hpp>
-#include <boost/type_traits/alignment_of.hpp>
-
-namespace boost {
- namespace detail {
- struct ms_init_tag { };
- struct ms_noinit_tag { };
-
- template<class T>
- struct ms_allocator_state;
-
- template<class T>
- struct ms_allocator_state<T[]> {
- typedef typename array_base<T>::type type;
-
- ms_allocator_state(std::size_t size_,
- type** result_)
- : size(size_ * array_total<T>::size),
- result(result_) {
- }
-
- std::size_t size;
-
- union {
- type** result;
- type* object;
- };
- };
-
- template<class T, std::size_t N>
- struct ms_allocator_state<T[N]> {
- typedef typename array_base<T>::type type;
-
- ms_allocator_state(type** result_)
- : result(result_) {
- }
-
- enum {
- size = array_total<T[N]>::size
- };
-
- union {
- type** result;
- type* object;
- };
- };
-
- template<class A, class T, class R>
- class as_allocator
- : public A {
- template<class A_, class T_, class R_>
- friend class as_allocator;
-
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- typedef std::allocator_traits<A> AT;
- typedef typename AT::template rebind_alloc<char> CA;
- typedef typename AT::template rebind_traits<char> CT;
-#else
- typedef typename A::template rebind<char>::other CA;
-#endif
-
- public:
- typedef A allocator_type;
-
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- typedef typename AT::value_type value_type;
- typedef typename AT::pointer pointer;
- typedef typename AT::const_pointer const_pointer;
- typedef typename AT::void_pointer void_pointer;
- typedef typename AT::const_void_pointer const_void_pointer;
- typedef typename AT::size_type size_type;
- typedef typename AT::difference_type difference_type;
-#else
- typedef typename A::value_type value_type;
- typedef typename A::pointer pointer;
- typedef typename A::const_pointer const_pointer;
- typedef typename A::size_type size_type;
- typedef typename A::difference_type difference_type;
- typedef typename A::reference reference;
- typedef typename A::const_reference const_reference;
- typedef void* void_pointer;
- typedef const void* const_void_pointer;
-#endif
-
- template<class U>
- struct rebind {
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- typedef as_allocator<typename AT::
- template rebind_alloc<U>, T, R> other;
-#else
- typedef as_allocator<typename A::
- template rebind<U>::other, T, R> other;
-#endif
- };
-
- typedef typename array_base<T>::type type;
-
- as_allocator(const A& allocator_, type** result)
- : A(allocator_),
- data(result) {
- }
-
- as_allocator(const A& allocator_, std::size_t size,
- type** result)
- : A(allocator_),
- data(size, result) {
- }
-
- template<class U>
- as_allocator(const as_allocator<U, T, R>& other)
- : A(other.allocator()),
- data(other.data) {
- }
-
- pointer allocate(size_type count, const_void_pointer = 0) {
- enum {
- M = boost::alignment_of<type>::value
- };
- std::size_t n1 = count * sizeof(value_type);
- std::size_t n2 = data.size * sizeof(type);
- std::size_t n3 = n2 + M;
- CA ca(allocator());
- void* p1 = ca.allocate(n1 + n3);
- void* p2 = static_cast<char*>(p1) + n1;
- (void)boost::alignment::align(M, n2, p2, n3);
- *data.result = static_cast<type*>(p2);
- return static_cast<value_type*>(p1);
- }
-
- void deallocate(pointer memory, size_type count) {
- enum {
- M = boost::alignment_of<type>::value
- };
- std::size_t n1 = count * sizeof(value_type);
- std::size_t n2 = data.size * sizeof(type) + M;
- char* p1 = reinterpret_cast<char*>(memory);
- CA ca(allocator());
- ca.deallocate(p1, n1 + n2);
- }
-
- const A& allocator() const {
- return static_cast<const A&>(*this);
- }
-
- A& allocator() {
- return static_cast<A&>(*this);
- }
-
- void set(type* memory) {
- data.object = memory;
- }
-
- void operator()() {
- if (data.object) {
- R tag;
- release(tag);
- }
- }
-
- private:
- void release(ms_init_tag) {
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- as_destroy(allocator(), data.object, data.size);
-#else
- ms_destroy(data.object, data.size);
-#endif
- }
-
- void release(ms_noinit_tag) {
- ms_destroy(data.object, data.size);
- }
-
- ms_allocator_state<T> data;
- };
-
- template<class A1, class A2, class T, class R>
- bool operator==(const as_allocator<A1, T, R>& a1,
- const as_allocator<A2, T, R>& a2) {
- return a1.allocator() == a2.allocator();
- }
-
- template<class A1, class A2, class T, class R>
- bool operator!=(const as_allocator<A1, T, R>& a1,
- const as_allocator<A2, T, R>& a2) {
- return a1.allocator() != a2.allocator();
- }
-
- template<class T, class Y = char>
- class ms_allocator;
-
- template<class T, class Y>
- class ms_allocator {
- template<class T_, class Y_>
- friend class ms_allocator;
-
- public:
- typedef typename array_base<T>::type type;
-
- typedef Y value_type;
- typedef Y* pointer;
- typedef const Y* const_pointer;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
- typedef Y& reference;
- typedef const Y& const_reference;
-
- template<class U>
- struct rebind {
- typedef ms_allocator<T, U> other;
- };
-
- ms_allocator(type** result)
- : data(result) {
- }
-
- ms_allocator(std::size_t size, type** result)
- : data(size, result) {
- }
-
- template<class U>
- ms_allocator(const ms_allocator<T, U>& other)
- : data(other.data) {
- }
-
- pointer allocate(size_type count, const void* = 0) {
- enum {
- M = boost::alignment_of<type>::value
- };
- std::size_t n1 = count * sizeof(Y);
- std::size_t n2 = data.size * sizeof(type);
- std::size_t n3 = n2 + M;
- void* p1 = ::operator new(n1 + n3);
- void* p2 = static_cast<char*>(p1) + n1;
- (void)boost::alignment::align(M, n2, p2, n3);
- *data.result = static_cast<type*>(p2);
- return static_cast<Y*>(p1);
- }
-
- void deallocate(pointer memory, size_type) {
- void* p1 = memory;
- ::operator delete(p1);
- }
-
-#if defined(BOOST_NO_CXX11_ALLOCATOR)
- pointer address(reference value) const {
- return &value;
- }
-
- const_pointer address(const_reference value) const {
- return &value;
- }
-
- size_type max_size() const {
- enum {
- N = static_cast<std::size_t>(-1) / sizeof(Y)
- };
- return N;
- }
-
- void construct(pointer memory, const_reference value) {
- void* p1 = memory;
- ::new(p1) Y(value);
- }
-
- void destroy(pointer memory) {
- (void)memory;
- memory->~Y();
- }
-#endif
-
- void set(type* memory) {
- data.object = memory;
- }
-
- void operator()() {
- if (data.object) {
- ms_destroy(data.object, data.size);
- }
- }
-
- private:
- ms_allocator_state<T> data;
- };
-
- template<class T, class Y1, class Y2>
- bool operator==(const ms_allocator<T, Y1>&,
- const ms_allocator<T, Y2>&) {
- return true;
- }
-
- template<class T, class Y1, class Y2>
- bool operator!=(const ms_allocator<T, Y1>&,
- const ms_allocator<T, Y2>&) {
- return false;
- }
-
- class ms_in_allocator_tag {
- public:
- void operator()(const void*) {
- }
- };
- }
-}
-
-#endif
diff --git a/boost/smart_ptr/detail/array_count_impl.hpp b/boost/smart_ptr/detail/array_count_impl.hpp
deleted file mode 100644
index b7c9617f0b..0000000000
--- a/boost/smart_ptr/detail/array_count_impl.hpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
-#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_COUNT_IMPL_HPP
-#define BOOST_SMART_PTR_DETAIL_ARRAY_COUNT_IMPL_HPP
-
-#include <boost/smart_ptr/detail/array_allocator.hpp>
-#include <boost/smart_ptr/detail/sp_counted_impl.hpp>
-
-namespace boost {
- namespace detail {
- template<class P, class A>
- class sp_counted_impl_pda<P, ms_in_allocator_tag, A>
- : public sp_counted_base {
- typedef ms_in_allocator_tag D;
- typedef sp_counted_impl_pda<P, D, A> Y;
- public:
- sp_counted_impl_pda(P, D, const A& allocator_)
- : allocator(allocator_) {
- }
-
- virtual void dispose() {
- allocator();
- }
-
- virtual void destroy() {
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- typedef typename std::allocator_traits<A>::
- template rebind_alloc<Y> YA;
- typedef typename std::allocator_traits<A>::
- template rebind_traits<Y> YT;
-#else
- typedef typename A::template rebind<Y>::other YA;
-#endif
- YA a1(allocator);
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- YT::destroy(a1, this);
- YT::deallocate(a1, this, 1);
-#else
- this->~Y();
- a1.deallocate(this, 1);
-#endif
- }
-
- virtual void* get_deleter(const sp_typeinfo&) {
- return &reinterpret_cast<char&>(allocator);
- }
-
- virtual void* get_untyped_deleter() {
- return &reinterpret_cast<char&>(allocator);
- }
-
- private:
- sp_counted_impl_pda(const sp_counted_impl_pda&);
- sp_counted_impl_pda& operator=(const sp_counted_impl_pda&);
-
- A allocator;
- };
- }
-}
-
-#endif
diff --git a/boost/smart_ptr/detail/array_traits.hpp b/boost/smart_ptr/detail/array_traits.hpp
deleted file mode 100644
index 819c5ba619..0000000000
--- a/boost/smart_ptr/detail/array_traits.hpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2012-2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
-#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP
-#define BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP
-
-#include <boost/type_traits/remove_cv.hpp>
-
-namespace boost {
- namespace detail {
- template<class T>
- struct array_base {
- typedef typename boost::remove_cv<T>::type type;
- };
-
- template<class T>
- struct array_base<T[]> {
- typedef typename array_base<T>::type type;
- };
-
- template<class T, std::size_t N>
- struct array_base<T[N]> {
- typedef typename array_base<T>::type type;
- };
-
- template<class T>
- struct array_total {
- enum {
- size = 1
- };
- };
-
- template<class T, std::size_t N>
- struct array_total<T[N]> {
- enum {
- size = N * array_total<T>::size
- };
- };
-
- template<class T>
- struct array_inner;
-
- template<class T>
- struct array_inner<T[]> {
- typedef T type;
- };
-
- template<class T, std::size_t N>
- struct array_inner<T[N]> {
- typedef T type;
- };
- }
-}
-
-#endif
diff --git a/boost/smart_ptr/detail/array_utility.hpp b/boost/smart_ptr/detail/array_utility.hpp
deleted file mode 100644
index 84029a1d77..0000000000
--- a/boost/smart_ptr/detail/array_utility.hpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (c) 2012-2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
-#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP
-#define BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP
-
-#include <boost/config.hpp>
-#include <boost/type_traits/has_trivial_constructor.hpp>
-#include <boost/type_traits/has_trivial_destructor.hpp>
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-#include <memory>
-#endif
-
-namespace boost {
- namespace detail {
- typedef boost::true_type ms_is_trivial;
- typedef boost::false_type ms_no_trivial;
-
- template<class T>
- inline void ms_destroy(T*, std::size_t, ms_is_trivial) {
- }
-
- template<class T>
- inline void ms_destroy(T* memory, std::size_t size, ms_no_trivial) {
- for (std::size_t i = size; i > 0;) {
- memory[--i].~T();
- }
- }
-
- template<class T>
- inline void ms_destroy(T* memory, std::size_t size) {
- boost::has_trivial_destructor<T> trivial;
- ms_destroy(memory, size, trivial);
- }
-
- template<class T>
- inline void ms_init(T* memory, std::size_t size, ms_is_trivial) {
- for (std::size_t i = 0; i < size; i++) {
- void* p1 = memory + i;
- ::new(p1) T();
- }
- }
-
- template<class T>
- inline void ms_init(T* memory, std::size_t size, ms_no_trivial) {
-#if !defined(BOOST_NO_EXCEPTIONS)
- std::size_t i = 0;
- try {
- for (; i < size; i++) {
- void* p1 = memory + i;
- ::new(p1) T();
- }
- } catch (...) {
- ms_destroy(memory, i);
- throw;
- }
-#else
- for (std::size_t i = 0; i < size; i++) {
- void* p1 = memory + i;
- ::new(p1) T();
- }
-#endif
- }
-
- template<class T>
- inline void ms_init(T* memory, std::size_t size) {
- boost::has_trivial_default_constructor<T> trivial;
- ms_init(memory, size, trivial);
- }
-
- template<class T, std::size_t N>
- inline void ms_init(T* memory, std::size_t size, const T* list) {
-#if !defined(BOOST_NO_EXCEPTIONS)
- std::size_t i = 0;
- try {
- for (; i < size; i++) {
- void* p1 = memory + i;
- ::new(p1) T(list[i % N]);
- }
- } catch (...) {
- ms_destroy(memory, i);
- throw;
- }
-#else
- for (std::size_t i = 0; i < size; i++) {
- void* p1 = memory + i;
- ::new(p1) T(list[i % N]);
- }
-#endif
- }
-
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- template<class T, class A>
- inline void as_destroy(const A& allocator, T* memory,
- std::size_t size) {
- typedef typename std::allocator_traits<A>::
- template rebind_alloc<T> TA;
- typedef typename std::allocator_traits<A>::
- template rebind_traits<T> TT;
- TA a2(allocator);
- for (std::size_t i = size; i > 0;) {
- TT::destroy(a2, &memory[--i]);
- }
- }
-
- template<class T, class A>
- inline void as_init(const A& allocator, T* memory, std::size_t size,
- ms_is_trivial) {
- typedef typename std::allocator_traits<A>::
- template rebind_alloc<T> TA;
- typedef typename std::allocator_traits<A>::
- template rebind_traits<T> TT;
- TA a2(allocator);
- for (std::size_t i = 0; i < size; i++) {
- TT::construct(a2, memory + i);
- }
- }
-
- template<class T, class A>
- inline void as_init(const A& allocator, T* memory, std::size_t size,
- ms_no_trivial) {
- typedef typename std::allocator_traits<A>::
- template rebind_alloc<T> TA;
- typedef typename std::allocator_traits<A>::
- template rebind_traits<T> TT;
- TA a2(allocator);
-#if !defined(BOOST_NO_EXCEPTIONS)
- std::size_t i = 0;
- try {
- for (; i < size; i++) {
- TT::construct(a2, memory + i);
- }
- } catch (...) {
- as_destroy(a2, memory, i);
- throw;
- }
-#else
- for (std::size_t i = 0; i < size; i++) {
- TT::construct(a2, memory + i);
- }
-#endif
- }
-
- template<class T, class A>
- inline void as_init(const A& allocator, T* memory, std::size_t size) {
- boost::has_trivial_default_constructor<T> trivial;
- as_init(allocator, memory, size, trivial);
- }
-
- template<class T, class A, std::size_t N>
- inline void as_init(const A& allocator, T* memory, std::size_t size,
- const T* list) {
- typedef typename std::allocator_traits<A>::
- template rebind_alloc<T> TA;
- typedef typename std::allocator_traits<A>::
- template rebind_traits<T> TT;
- TA a2(allocator);
-#if !defined(BOOST_NO_EXCEPTIONS)
- std::size_t i = 0;
- try {
- for (; i < size; i++) {
- TT::construct(a2, memory + i, list[i % N]);
- }
- } catch (...) {
- as_destroy(a2, memory, i);
- throw;
- }
-#else
- for (std::size_t i = 0; i < size; i++) {
- TT::construct(a2, memory + i, list[i % N]);
- }
-#endif
- }
-#endif
-
- template<class T>
- inline void ms_noinit(T*, std::size_t, ms_is_trivial) {
- }
-
- template<class T>
- inline void ms_noinit(T* memory, std::size_t size, ms_no_trivial) {
-#if !defined(BOOST_NO_EXCEPTIONS)
- std::size_t i = 0;
- try {
- for (; i < size; i++) {
- void* p1 = memory + i;
- ::new(p1) T;
- }
- } catch (...) {
- ms_destroy(memory, i);
- throw;
- }
-#else
- for (std::size_t i = 0; i < size; i++) {
- void* p1 = memory + i;
- ::new(p1) T;
- }
-#endif
- }
-
- template<class T>
- inline void ms_noinit(T* memory, std::size_t size) {
- boost::has_trivial_default_constructor<T> trivial;
- ms_noinit(memory, size, trivial);
- }
- }
-}
-
-#endif
diff --git a/boost/smart_ptr/detail/shared_count.hpp b/boost/smart_ptr/detail/shared_count.hpp
index 7996aa4325..9813842300 100644
--- a/boost/smart_ptr/detail/shared_count.hpp
+++ b/boost/smart_ptr/detail/shared_count.hpp
@@ -249,18 +249,8 @@ public:
try
{
-#if !defined( BOOST_NO_CXX11_ALLOCATOR )
-
- impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
- pi_ = pi;
- std::allocator_traits<A2>::construct( a2, pi, p, d, a );
-
-#else
-
- pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
+ pi_ = a2.allocate( 1 );
::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
-
-#endif
}
catch(...)
{
@@ -276,28 +266,11 @@ public:
#else
-#if !defined( BOOST_NO_CXX11_ALLOCATOR )
-
- impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
- pi_ = pi;
-
-#else
-
- pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
-
-#endif
+ pi_ = a2.allocate( 1 );
if( pi_ != 0 )
{
-#if !defined( BOOST_NO_CXX11_ALLOCATOR )
-
- std::allocator_traits<A2>::construct( a2, pi, p, d, a );
-
-#else
-
::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
-
-#endif
}
else
{
@@ -333,18 +306,8 @@ public:
try
{
-#if !defined( BOOST_NO_CXX11_ALLOCATOR )
-
- impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
- pi_ = pi;
- std::allocator_traits<A2>::construct( a2, pi, p, a );
-
-#else
-
- pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
+ pi_ = a2.allocate( 1 );
::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
-
-#endif
}
catch(...)
{
@@ -360,28 +323,11 @@ public:
#else
-#if !defined( BOOST_NO_CXX11_ALLOCATOR )
-
- impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
- pi_ = pi;
-
-#else
-
- pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
-
-#endif
+ pi_ = a2.allocate( 1 );
if( pi_ != 0 )
{
-#if !defined( BOOST_NO_CXX11_ALLOCATOR )
-
- std::allocator_traits<A2>::construct( a2, pi, p, a );
-
-#else
-
::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
-
-#endif
}
else
{
diff --git a/boost/smart_ptr/detail/sp_counted_base.hpp b/boost/smart_ptr/detail/sp_counted_base.hpp
index 83ede23173..438613765b 100644
--- a/boost/smart_ptr/detail/sp_counted_base.hpp
+++ b/boost/smart_ptr/detail/sp_counted_base.hpp
@@ -20,7 +20,7 @@
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
-#if defined( __clang__ ) && defined( __has_extension )
+#if !defined( __c2__ ) && defined( __clang__ ) && defined( __has_extension )
# if __has_extension( __c_atomic__ )
# define BOOST_SP_HAS_CLANG_C11_ATOMICS
# endif
diff --git a/boost/smart_ptr/detail/sp_counted_impl.hpp b/boost/smart_ptr/detail/sp_counted_impl.hpp
index 1222f3c9f4..b29769e3af 100644
--- a/boost/smart_ptr/detail/sp_counted_impl.hpp
+++ b/boost/smart_ptr/detail/sp_counted_impl.hpp
@@ -236,16 +236,8 @@ public:
A2 a2( a_ );
-#if !defined( BOOST_NO_CXX11_ALLOCATOR )
-
- std::allocator_traits<A2>::destroy( a2, this );
-
-#else
-
this->~this_type();
-#endif
-
a2.deallocate( this, 1 );
}
diff --git a/boost/smart_ptr/detail/sp_has_sync.hpp b/boost/smart_ptr/detail/sp_has_sync.hpp
index 16de21d379..e1debf0cc9 100644
--- a/boost/smart_ptr/detail/sp_has_sync.hpp
+++ b/boost/smart_ptr/detail/sp_has_sync.hpp
@@ -22,15 +22,15 @@
#ifndef BOOST_SP_NO_SYNC
-#if defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 )
+#if !defined( __c2__ ) && defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 )
# define BOOST_SP_HAS_SYNC
-#elif defined( __IBMCPP__ ) && ( __IBMCPP__ >= 1210 )
+#elif defined( __IBMCPP__ ) && ( __IBMCPP__ >= 1210 ) && !defined( __COMPILER_VER__ )
# define BOOST_SP_HAS_SYNC
-#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
+#elif !defined( __c2__ ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
#define BOOST_SP_HAS_SYNC
diff --git a/boost/smart_ptr/detail/sp_if_array.hpp b/boost/smart_ptr/detail/sp_if_array.hpp
deleted file mode 100644
index 9a2c1e0baa..0000000000
--- a/boost/smart_ptr/detail/sp_if_array.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012-2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
-#ifndef BOOST_SMART_PTR_DETAIL_SP_IF_ARRAY_HPP
-#define BOOST_SMART_PTR_DETAIL_SP_IF_ARRAY_HPP
-
-#include <boost/smart_ptr/shared_ptr.hpp>
-
-namespace boost {
- namespace detail {
- template<class T>
- struct sp_if_array;
-
- template<class T>
- struct sp_if_array<T[]> {
- typedef boost::shared_ptr<T[]> type;
- };
-
- template<class T>
- struct sp_if_size_array;
-
- template<class T, std::size_t N>
- struct sp_if_size_array<T[N]> {
- typedef boost::shared_ptr<T[N]> type;
- };
- }
-}
-
-#endif
diff --git a/boost/smart_ptr/detail/sp_noexcept.hpp b/boost/smart_ptr/detail/sp_noexcept.hpp
new file mode 100644
index 0000000000..6818dce38d
--- /dev/null
+++ b/boost/smart_ptr/detail/sp_noexcept.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_NOEXCEPT_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_NOEXCEPT_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_noexcept.hpp
+//
+// Copyright 2016 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/config.hpp>
+
+#if defined( BOOST_MSVC ) && BOOST_MSVC >= 1700 && BOOST_MSVC < 1900
+
+#define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT_OR_NOTHROW
+
+#else
+
+#define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT
+
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_NOEXCEPT_HPP_INCLUDED
diff --git a/boost/smart_ptr/enable_shared_from_this.hpp b/boost/smart_ptr/enable_shared_from_this.hpp
index 4e3f243d28..642403a0a3 100644
--- a/boost/smart_ptr/enable_shared_from_this.hpp
+++ b/boost/smart_ptr/enable_shared_from_this.hpp
@@ -15,6 +15,7 @@
#include <boost/smart_ptr/weak_ptr.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
@@ -25,20 +26,20 @@ template<class T> class enable_shared_from_this
{
protected:
- enable_shared_from_this() BOOST_NOEXCEPT
+ enable_shared_from_this() BOOST_SP_NOEXCEPT
{
}
- enable_shared_from_this(enable_shared_from_this const &) BOOST_NOEXCEPT
+ enable_shared_from_this(enable_shared_from_this const &) BOOST_SP_NOEXCEPT
{
}
- enable_shared_from_this & operator=(enable_shared_from_this const &) BOOST_NOEXCEPT
+ enable_shared_from_this & operator=(enable_shared_from_this const &) BOOST_SP_NOEXCEPT
{
return *this;
}
- ~enable_shared_from_this() BOOST_NOEXCEPT // ~weak_ptr<T> newer throws, so this call also must not throw
+ ~enable_shared_from_this() BOOST_SP_NOEXCEPT // ~weak_ptr<T> newer throws, so this call also must not throw
{
}
diff --git a/boost/smart_ptr/intrusive_ptr.hpp b/boost/smart_ptr/intrusive_ptr.hpp
index 1e9339732b..0e46212165 100644
--- a/boost/smart_ptr/intrusive_ptr.hpp
+++ b/boost/smart_ptr/intrusive_ptr.hpp
@@ -19,6 +19,7 @@
#include <boost/detail/workaround.hpp>
#include <boost/smart_ptr/detail/sp_convertible.hpp>
#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config/no_tr1/functional.hpp> // for std::less
@@ -59,7 +60,7 @@ public:
typedef T element_type;
- BOOST_CONSTEXPR intrusive_ptr() BOOST_NOEXCEPT : px( 0 )
+ BOOST_CONSTEXPR intrusive_ptr() BOOST_SP_NOEXCEPT : px( 0 )
{
}
@@ -111,12 +112,12 @@ public:
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
- intrusive_ptr(intrusive_ptr && rhs) BOOST_NOEXCEPT : px( rhs.px )
+ intrusive_ptr(intrusive_ptr && rhs) BOOST_SP_NOEXCEPT : px( rhs.px )
{
rhs.px = 0;
}
- intrusive_ptr & operator=(intrusive_ptr && rhs) BOOST_NOEXCEPT
+ intrusive_ptr & operator=(intrusive_ptr && rhs) BOOST_SP_NOEXCEPT
{
this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
return *this;
diff --git a/boost/smart_ptr/make_shared_array.hpp b/boost/smart_ptr/make_shared_array.hpp
index c48f5070b6..2eaf4db71b 100644
--- a/boost/smart_ptr/make_shared_array.hpp
+++ b/boost/smart_ptr/make_shared_array.hpp
@@ -1,158 +1,66 @@
/*
- * Copyright (c) 2012-2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
+Copyright 2012-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_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
-#include <boost/smart_ptr/detail/array_count_impl.hpp>
-#include <boost/smart_ptr/detail/sp_if_array.hpp>
+#include <boost/smart_ptr/allocate_shared_array.hpp>
namespace boost {
- template<class T>
- inline typename boost::detail::sp_if_array<T>::type
- make_shared(std::size_t size) {
- typedef typename boost::detail::array_inner<T>::type T1;
- typedef typename boost::detail::array_base<T1>::type T2;
- typedef boost::detail::ms_allocator<T> A1;
- typedef boost::detail::ms_in_allocator_tag D1;
- std::size_t n1 = size * boost::detail::array_total<T1>::size;
- T1* p1 = 0;
- T2* p2 = 0;
- D1 d1;
- A1 a1(size, &p2);
- shared_ptr<T> s1(p1, d1, a1);
- A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
- a2->set(0);
- boost::detail::ms_init(p2, n1);
- a2->set(p2);
- p1 = reinterpret_cast<T1*>(p2);
- return shared_ptr<T>(s1, p1);
- }
- template<class T>
- inline typename boost::detail::sp_if_size_array<T>::type
- make_shared() {
- typedef typename boost::detail::array_inner<T>::type T1;
- typedef typename boost::detail::array_base<T1>::type T2;
- typedef boost::detail::ms_allocator<T> A1;
- typedef boost::detail::ms_in_allocator_tag D1;
- enum {
- N = boost::detail::array_total<T>::size
- };
- T1* p1 = 0;
- T2* p2 = 0;
- D1 d1;
- A1 a1(&p2);
- shared_ptr<T> s1(p1, d1, a1);
- A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
- a2->set(0);
- boost::detail::ms_init(p2, N);
- a2->set(p2);
- p1 = reinterpret_cast<T1*>(p2);
- return shared_ptr<T>(s1, p1);
- }
+template<class T>
+inline typename detail::sp_if_size_array<T>::type
+make_shared()
+{
+ return boost::allocate_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>());
+}
+
+template<class T>
+inline typename detail::sp_if_size_array<T>::type
+make_shared(const typename detail::sp_array_element<T>::type& value)
+{
+ return boost::allocate_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), value);
+}
- template<class T>
- inline typename boost::detail::sp_if_array<T>::type
- make_shared(std::size_t size,
- const typename boost::detail::array_inner<T>::type& value) {
- typedef typename boost::detail::array_inner<T>::type T1;
- typedef typename boost::detail::array_base<T1>::type T2;
- typedef const T2 T3;
- typedef boost::detail::ms_allocator<T> A1;
- typedef boost::detail::ms_in_allocator_tag D1;
- enum {
- M = boost::detail::array_total<T1>::size
- };
- std::size_t n1 = M * size;
- T1* p1 = 0;
- T2* p2 = 0;
- T3* p3 = reinterpret_cast<T3*>(&value);
- D1 d1;
- A1 a1(size, &p2);
- shared_ptr<T> s1(p1, d1, a1);
- A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
- a2->set(0);
- boost::detail::ms_init<T2, M>(p2, n1, p3);
- a2->set(p2);
- p1 = reinterpret_cast<T1*>(p2);
- return shared_ptr<T>(s1, p1);
- }
+template<class T>
+inline typename detail::sp_if_array<T>::type
+make_shared(std::size_t size)
+{
+ return boost::allocate_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), size);
+}
- template<class T>
- inline typename boost::detail::sp_if_size_array<T>::type
- make_shared(const typename boost::detail::array_inner<T>::type& value) {
- typedef typename boost::detail::array_inner<T>::type T1;
- typedef typename boost::detail::array_base<T1>::type T2;
- typedef const T2 T3;
- typedef boost::detail::ms_allocator<T> A1;
- typedef boost::detail::ms_in_allocator_tag D1;
- enum {
- M = boost::detail::array_total<T1>::size,
- N = boost::detail::array_total<T>::size
- };
- T1* p1 = 0;
- T2* p2 = 0;
- T3* p3 = reinterpret_cast<T3*>(&value);
- D1 d1;
- A1 a1(&p2);
- shared_ptr<T> s1(p1, d1, a1);
- A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
- a2->set(0);
- boost::detail::ms_init<T2, M>(p2, N, p3);
- a2->set(p2);
- p1 = reinterpret_cast<T1*>(p2);
- return shared_ptr<T>(s1, p1);
- }
+template<class T>
+inline typename detail::sp_if_array<T>::type
+make_shared(std::size_t size,
+ const typename detail::sp_array_element<T>::type& value)
+{
+ return boost::allocate_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), size, value);
+}
- template<class T>
- inline typename boost::detail::sp_if_array<T>::type
- make_shared_noinit(std::size_t size) {
- typedef typename boost::detail::array_inner<T>::type T1;
- typedef typename boost::detail::array_base<T1>::type T2;
- typedef boost::detail::ms_allocator<T> A1;
- typedef boost::detail::ms_in_allocator_tag D1;
- std::size_t n1 = size * boost::detail::array_total<T1>::size;
- T1* p1 = 0;
- T2* p2 = 0;
- D1 d1;
- A1 a1(size, &p2);
- shared_ptr<T> s1(p1, d1, a1);
- A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
- a2->set(0);
- boost::detail::ms_noinit(p2, n1);
- a2->set(p2);
- p1 = reinterpret_cast<T1*>(p2);
- return shared_ptr<T>(s1, p1);
- }
+template<class T>
+inline typename detail::sp_if_size_array<T>::type
+make_shared_noinit()
+{
+ return allocate_shared_noinit<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>());
+}
- template<class T>
- inline typename boost::detail::sp_if_size_array<T>::type
- make_shared_noinit() {
- typedef typename boost::detail::array_inner<T>::type T1;
- typedef typename boost::detail::array_base<T1>::type T2;
- typedef boost::detail::ms_allocator<T> A1;
- typedef boost::detail::ms_in_allocator_tag D1;
- enum {
- N = boost::detail::array_total<T>::size
- };
- T1* p1 = 0;
- T2* p2 = 0;
- D1 d1;
- A1 a1(&p2);
- shared_ptr<T> s1(p1, d1, a1);
- A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
- a2->set(0);
- boost::detail::ms_noinit(p2, N);
- a2->set(p2);
- p1 = reinterpret_cast<T1*>(p2);
- return shared_ptr<T>(s1, p1);
- }
+template<class T>
+inline typename detail::sp_if_array<T>::type
+make_shared_noinit(std::size_t size)
+{
+ return allocate_shared_noinit<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), size);
}
+} /* boost */
+
#endif
diff --git a/boost/smart_ptr/make_unique.hpp b/boost/smart_ptr/make_unique.hpp
index d054e3dfe1..eed503392b 100644
--- a/boost/smart_ptr/make_unique.hpp
+++ b/boost/smart_ptr/make_unique.hpp
@@ -1,10 +1,9 @@
/*
-(c) 2014-2015 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_HPP
#define BOOST_SMART_PTR_MAKE_UNIQUE_HPP
@@ -15,6 +14,7 @@ http://boost.org/LICENSE_1_0.txt
namespace boost {
namespace detail {
+
template<class T>
struct up_if_object {
typedef std::unique_ptr<T> type;
@@ -56,10 +56,12 @@ template<class T>
struct up_element<T[]> {
typedef T type;
};
+
} /* detail */
template<class T>
-inline typename detail::up_if_object<T>::type make_unique()
+inline typename detail::up_if_object<T>::type
+make_unique()
{
return std::unique_ptr<T>(new T());
}
@@ -67,7 +69,7 @@ inline typename detail::up_if_object<T>::type make_unique()
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class... Args>
inline typename detail::up_if_object<T>::type
- make_unique(Args&&... args)
+make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
@@ -75,31 +77,34 @@ inline typename detail::up_if_object<T>::type
template<class T>
inline typename detail::up_if_object<T>::type
- make_unique(typename detail::up_remove_reference<T>::type&& value)
+make_unique(typename detail::up_remove_reference<T>::type&& value)
{
return std::unique_ptr<T>(new T(std::move(value)));
}
template<class T>
-inline typename detail::up_if_object<T>::type make_unique_noinit()
+inline typename detail::up_if_object<T>::type
+make_unique_noinit()
{
return std::unique_ptr<T>(new T);
}
template<class T>
-inline typename detail::up_if_array<T>::type make_unique(std::size_t n)
+inline typename detail::up_if_array<T>::type
+make_unique(std::size_t size)
{
- return std::unique_ptr<T>(new
- typename detail::up_element<T>::type[n]());
+ return std::unique_ptr<T>(new typename
+ detail::up_element<T>::type[size]());
}
template<class T>
inline typename detail::up_if_array<T>::type
- make_unique_noinit(std::size_t n)
+make_unique_noinit(std::size_t size)
{
- return std::unique_ptr<T>(new
- typename detail::up_element<T>::type[n]);
+ return std::unique_ptr<T>(new typename
+ detail::up_element<T>::type[size]);
}
+
} /* boost */
#endif
diff --git a/boost/smart_ptr/owner_less.hpp b/boost/smart_ptr/owner_less.hpp
index 6899325bd6..75d182c121 100644
--- a/boost/smart_ptr/owner_less.hpp
+++ b/boost/smart_ptr/owner_less.hpp
@@ -5,6 +5,7 @@
// owner_less.hpp
//
// Copyright (c) 2008 Frank Mori Hess
+// Copyright (c) 2016 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -13,44 +14,20 @@
// See http://www.boost.org/libs/smart_ptr/smart_ptr.htm for documentation.
//
-#include <functional>
-
namespace boost
{
- template<typename T> class shared_ptr;
- template<typename T> class weak_ptr;
-
- namespace detail
- {
- template<typename T, typename U>
- struct generic_owner_less : public std::binary_function<T, T, bool>
- {
- bool operator()(const T &lhs, const T &rhs) const
- {
- return lhs.owner_before(rhs);
- }
- bool operator()(const T &lhs, const U &rhs) const
- {
- return lhs.owner_before(rhs);
- }
- bool operator()(const U &lhs, const T &rhs) const
- {
- return lhs.owner_before(rhs);
- }
- };
- } // namespace detail
- template<typename T> struct owner_less;
-
- template<typename T>
- struct owner_less<shared_ptr<T> >:
- public detail::generic_owner_less<shared_ptr<T>, weak_ptr<T> >
- {};
+template<class T = void> struct owner_less
+{
+ typedef bool result_type;
+ typedef T first_argument_type;
+ typedef T second_argument_type;
- template<typename T>
- struct owner_less<weak_ptr<T> >:
- public detail::generic_owner_less<weak_ptr<T>, shared_ptr<T> >
- {};
+ template<class U, class V> bool operator()( U const & u, V const & v ) const
+ {
+ return u.owner_before( v );
+ }
+};
} // namespace boost
diff --git a/boost/smart_ptr/scoped_array.hpp b/boost/smart_ptr/scoped_array.hpp
index e395e28f85..f847c094e4 100644
--- a/boost/smart_ptr/scoped_array.hpp
+++ b/boost/smart_ptr/scoped_array.hpp
@@ -15,6 +15,7 @@
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/detail/workaround.hpp>
@@ -54,7 +55,7 @@ public:
typedef T element_type;
- explicit scoped_array( T * p = 0 ) BOOST_NOEXCEPT : px( p )
+ explicit scoped_array( T * p = 0 ) BOOST_SP_NOEXCEPT : px( p )
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_array_constructor_hook( px );
diff --git a/boost/smart_ptr/scoped_ptr.hpp b/boost/smart_ptr/scoped_ptr.hpp
index d5d8720f52..8fd8a180fb 100644
--- a/boost/smart_ptr/scoped_ptr.hpp
+++ b/boost/smart_ptr/scoped_ptr.hpp
@@ -16,6 +16,7 @@
#include <boost/checked_delete.hpp>
#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/detail/workaround.hpp>
#ifndef BOOST_NO_AUTO_PTR
@@ -62,7 +63,7 @@ public:
typedef T element_type;
- explicit scoped_ptr( T * p = 0 ): px( p ) // never throws
+ explicit scoped_ptr( T * p = 0 ) BOOST_SP_NOEXCEPT : px( p ) // never throws
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_constructor_hook( px );
diff --git a/boost/smart_ptr/shared_array.hpp b/boost/smart_ptr/shared_array.hpp
index fd58071be0..2e5cb134a3 100644
--- a/boost/smart_ptr/shared_array.hpp
+++ b/boost/smart_ptr/shared_array.hpp
@@ -24,6 +24,7 @@
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/detail/shared_count.hpp>
#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/detail/workaround.hpp>
#include <cstddef> // for std::ptrdiff_t
@@ -53,13 +54,13 @@ public:
typedef T element_type;
- shared_array() BOOST_NOEXCEPT : px( 0 ), pn()
+ shared_array() BOOST_SP_NOEXCEPT : px( 0 ), pn()
{
}
#if !defined( BOOST_NO_CXX11_NULLPTR )
- shared_array( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn()
+ shared_array( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn()
{
}
@@ -95,11 +96,11 @@ public:
// ... except in C++0x, move disables the implicit copy
- shared_array( shared_array const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
+ shared_array( shared_array const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
{
}
- shared_array( shared_array && r ) BOOST_NOEXCEPT : px( r.px ), pn()
+ shared_array( shared_array && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn()
{
pn.swap( r.pn );
r.px = 0;
@@ -133,7 +134,7 @@ public:
// assignment
- shared_array & operator=( shared_array const & r ) BOOST_NOEXCEPT
+ shared_array & operator=( shared_array const & r ) BOOST_SP_NOEXCEPT
{
this_type( r ).swap( *this );
return *this;
@@ -152,7 +153,7 @@ public:
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
- shared_array & operator=( shared_array && r ) BOOST_NOEXCEPT
+ shared_array & operator=( shared_array && r ) BOOST_SP_NOEXCEPT
{
this_type( static_cast< shared_array && >( r ) ).swap( *this );
return *this;
diff --git a/boost/smart_ptr/shared_ptr.hpp b/boost/smart_ptr/shared_ptr.hpp
index 77f68bebd0..e33707b3bc 100644
--- a/boost/smart_ptr/shared_ptr.hpp
+++ b/boost/smart_ptr/shared_ptr.hpp
@@ -30,6 +30,7 @@
#include <boost/smart_ptr/detail/sp_convertible.hpp>
#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
#include <boost/smart_ptr/detail/spinlock_pool.hpp>
@@ -344,13 +345,13 @@ public:
typedef typename boost::detail::sp_element< T >::type element_type;
- shared_ptr() BOOST_NOEXCEPT : px( 0 ), pn() // never throws in 1.30+
+ shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn() // never throws in 1.30+
{
}
#if !defined( BOOST_NO_CXX11_NULLPTR )
- shared_ptr( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws
+ shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn() // never throws
{
}
@@ -402,7 +403,7 @@ public:
// ... except in C++0x, move disables the implicit copy
- shared_ptr( shared_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
+ shared_ptr( shared_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
{
}
@@ -521,7 +522,7 @@ public:
// assignment
- shared_ptr & operator=( shared_ptr const & r ) BOOST_NOEXCEPT
+ shared_ptr & operator=( shared_ptr const & r ) BOOST_SP_NOEXCEPT
{
this_type(r).swap(*this);
return *this;
@@ -605,7 +606,7 @@ public:
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
- shared_ptr( shared_ptr && r ) BOOST_NOEXCEPT : px( r.px ), pn()
+ shared_ptr( shared_ptr && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn()
{
pn.swap( r.pn );
r.px = 0;
@@ -629,7 +630,7 @@ public:
r.px = 0;
}
- shared_ptr & operator=( shared_ptr && r ) BOOST_NOEXCEPT
+ shared_ptr & operator=( shared_ptr && r ) BOOST_SP_NOEXCEPT
{
this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
return *this;
@@ -882,6 +883,50 @@ template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U>
return shared_ptr<T>( r, p );
}
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r ) BOOST_NOEXCEPT
+{
+ (void) static_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = static_cast< E* >( r.get() );
+ 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
+{
+ (void) const_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = const_cast< E* >( r.get() );
+ 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
+{
+ (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = dynamic_cast< E* >( r.get() );
+ 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
+{
+ (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = reinterpret_cast< E* >( r.get() );
+ return shared_ptr<T>( std::move(r), p );
+}
+
+#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
// 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
diff --git a/boost/smart_ptr/weak_ptr.hpp b/boost/smart_ptr/weak_ptr.hpp
index e3e9ad9bde..f3411f7225 100644
--- a/boost/smart_ptr/weak_ptr.hpp
+++ b/boost/smart_ptr/weak_ptr.hpp
@@ -16,6 +16,7 @@
#include <memory> // boost.TR1 include order fix
#include <boost/smart_ptr/detail/shared_count.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
namespace boost
{
@@ -31,7 +32,7 @@ public:
typedef typename boost::detail::sp_element< T >::type element_type;
- weak_ptr() BOOST_NOEXCEPT : px(0), pn() // never throws in 1.30+
+ weak_ptr() BOOST_SP_NOEXCEPT : px(0), pn() // never throws in 1.30+
{
}
@@ -41,11 +42,11 @@ public:
// ... except in C++0x, move disables the implicit copy
- weak_ptr( weak_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
+ weak_ptr( weak_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
{
}
- weak_ptr & operator=( weak_ptr const & r ) BOOST_NOEXCEPT
+ weak_ptr & operator=( weak_ptr const & r ) BOOST_SP_NOEXCEPT
{
px = r.px;
pn = r.pn;
@@ -106,13 +107,13 @@ public:
// for better efficiency in the T == Y case
weak_ptr( weak_ptr && r )
- BOOST_NOEXCEPT : px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
+ BOOST_SP_NOEXCEPT : px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
{
r.px = 0;
}
// for better efficiency in the T == Y case
- weak_ptr & operator=( weak_ptr && r ) BOOST_NOEXCEPT
+ weak_ptr & operator=( weak_ptr && r ) BOOST_SP_NOEXCEPT
{
this_type( static_cast< weak_ptr && >( r ) ).swap( *this );
return *this;
diff --git a/boost/system/cygwin_error.hpp b/boost/system/cygwin_error.hpp
index ea3528b66d..4f91cf3d73 100644
--- a/boost/system/cygwin_error.hpp
+++ b/boost/system/cygwin_error.hpp
@@ -7,8 +7,8 @@
// See library home page at http://www.boost.org/libs/system
-#ifndef BOOST_CYGWIN_ERROR_HPP
-#define BOOST_CYGWIN_ERROR_HPP
+#ifndef BOOST_SYSTEM_CYGWIN_ERROR_HPP
+#define BOOST_SYSTEM_CYGWIN_ERROR_HPP
// This header is effectively empty for compiles on operating systems where
// it is not applicable.
@@ -53,4 +53,4 @@ namespace boost
#endif // __CYGWIN__
-#endif // BOOST_CYGWIN_ERROR_HPP
+#endif // BOOST_SYSTEM_CYGWIN_ERROR_HPP
diff --git a/boost/system/error_code.hpp b/boost/system/error_code.hpp
index d419f3701b..b6ff6e4bad 100644
--- a/boost/system/error_code.hpp
+++ b/boost/system/error_code.hpp
@@ -8,8 +8,8 @@
// See library home page at http://www.boost.org/libs/system
-#ifndef BOOST_ERROR_CODE_HPP
-#define BOOST_ERROR_CODE_HPP
+#ifndef BOOST_SYSTEM_ERROR_CODE_HPP
+#define BOOST_SYSTEM_ERROR_CODE_HPP
#include <boost/system/config.hpp>
#include <boost/cstdint.hpp>
@@ -39,8 +39,9 @@ namespace boost
namespace system
{
- class error_code;
- class error_condition;
+ class error_code; // values defined by the operating system
+ class error_condition; // portable generic values defined below, but ultimately
+ // based on the POSIX standard
// "Concept" helpers ---------------------------------------------------//
@@ -218,9 +219,9 @@ namespace boost
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 = generic_category();
- static const error_category & errno_ecat = generic_category();
- static const error_category & native_ecat = system_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 -----------------------------------------------//
@@ -515,6 +516,6 @@ namespace boost
# include <boost/system/detail/error_code.ipp>
# endif
-#endif // BOOST_ERROR_CODE_HPP
+#endif // BOOST_SYSTEM_ERROR_CODE_HPP
diff --git a/boost/system/linux_error.hpp b/boost/system/linux_error.hpp
index 0eb22bf25a..0873a7cd92 100644
--- a/boost/system/linux_error.hpp
+++ b/boost/system/linux_error.hpp
@@ -7,8 +7,8 @@
// See library home page at http://www.boost.org/libs/system
-#ifndef BOOST_LINUX_ERROR_HPP
-#define BOOST_LINUX_ERROR_HPP
+#ifndef BOOST_SYSTEM_LINUX_ERROR_HPP
+#define BOOST_SYSTEM_LINUX_ERROR_HPP
// This header is effectively empty for compiles on operating systems where
// it is not applicable.
@@ -107,4 +107,4 @@ namespace boost
#endif // Linux
-#endif // BOOST_LINUX_ERROR_HPP
+#endif // BOOST_SYSTEM_LINUX_ERROR_HPP
diff --git a/boost/system/system_error.hpp b/boost/system/system_error.hpp
index b306aae4b9..d98b4bcf84 100644
--- a/boost/system/system_error.hpp
+++ b/boost/system/system_error.hpp
@@ -5,8 +5,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_SYSTEM_ERROR_HPP
-#define BOOST_SYSTEM_ERROR_HPP
+#ifndef BOOST_SYSTEM_SYSTEM_ERROR_HPP
+#define BOOST_SYSTEM_SYSTEM_ERROR_HPP
#include <string>
#include <stdexcept>
@@ -79,6 +79,6 @@ namespace boost
} // namespace system
} // namespace boost
-#endif // BOOST_SYSTEM_ERROR_HPP
+#endif // BOOST_SYSTEM_SYSTEM_ERROR_HPP
diff --git a/boost/system/windows_error.hpp b/boost/system/windows_error.hpp
index 9d9d206c6b..38d628404c 100644
--- a/boost/system/windows_error.hpp
+++ b/boost/system/windows_error.hpp
@@ -7,8 +7,8 @@
// See library home page at http://www.boost.org/libs/system
-#ifndef BOOST_WINDOWS_ERROR_HPP
-#define BOOST_WINDOWS_ERROR_HPP
+#ifndef BOOST_SYSTEM_WINDOWS_ERROR_HPP
+#define BOOST_SYSTEM_WINDOWS_ERROR_HPP
// This header is effectively empty for compiles on operating systems where
// it is not applicable.
@@ -123,4 +123,4 @@ namespace boost
#endif // BOOST_WINDOWS_API
-#endif // BOOST_WINDOWS_ERROR_HPP
+#endif // BOOST_SYSTEM_WINDOWS_ERROR_HPP
diff --git a/boost/test/detail/throw_exception.hpp b/boost/test/detail/throw_exception.hpp
index 1568ec3c29..3f2f4687d3 100644
--- a/boost/test/detail/throw_exception.hpp
+++ b/boost/test/detail/throw_exception.hpp
@@ -13,9 +13,9 @@
#define BOOST_TEST_DETAIL_THROW_EXCEPTION_HPP
// Boost
-#include <boost/config.hpp> // BOOST_NO_EXCEPTION
+#include <boost/config.hpp> // BOOST_NO_EXCEPTIONS
-#ifdef BOOST_NO_EXCEPTION
+#ifdef BOOST_NO_EXCEPTIONS
// C RUNTIME
#include <stdlib.h>
diff --git a/boost/test/execution_monitor.hpp b/boost/test/execution_monitor.hpp
index f53348abe1..adfb0336ca 100644
--- a/boost/test/execution_monitor.hpp
+++ b/boost/test/execution_monitor.hpp
@@ -66,6 +66,21 @@
#endif
+#if defined(BOOST_SEH_BASED_SIGNAL_HANDLING) && !defined(UNDER_CE)
+ //! Indicates tha the floating point exception handling is supported
+ //! through SEH
+ #define BOOST_TEST_FPE_SUPPORT_WITH_SEH__
+#elif !defined(BOOST_SEH_BASED_SIGNAL_HANDLING) && !defined(UNDER_CE)
+ #if !defined(BOOST_NO_FENV_H) && !defined(BOOST_CLANG) && \
+ defined(__GLIBC__) && defined(__USE_GNU) && \
+ !(defined(__UCLIBC__) || defined(__nios2__) || defined(__microblaze__))
+ //! Indicates that floating point exception handling is supported for the
+ //! non SEH version of it, for the GLIBC extensions only
+ // see dicussions on the related topic: https://svn.boost.org/trac/boost/ticket/11756
+ #define BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__
+ #endif
+#endif
+
// Additional macro documentations not being generated without this hack
#ifdef BOOST_TEST_DOXYGEN_DOC__
@@ -489,7 +504,7 @@ namespace fpe {
enum masks {
BOOST_FPE_OFF = 0,
-#ifdef BOOST_SEH_BASED_SIGNAL_HANDLING /* *** */
+#if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__) /* *** */
BOOST_FPE_DIVBYZERO = EM_ZERODIVIDE,
BOOST_FPE_INEXACT = EM_INEXACT,
BOOST_FPE_INVALID = EM_INVALID,
@@ -498,7 +513,7 @@ enum masks {
BOOST_FPE_ALL = MCW_EM,
-#elif defined(BOOST_NO_FENV_H) || defined(BOOST_CLANG) /* *** */
+#elif !defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)/* *** */
BOOST_FPE_ALL = BOOST_FPE_OFF,
#else /* *** */
diff --git a/boost/test/impl/compiler_log_formatter.ipp b/boost/test/impl/compiler_log_formatter.ipp
index 8c76788109..a4e045cae0 100644
--- a/boost/test/impl/compiler_log_formatter.ipp
+++ b/boost/test/impl/compiler_log_formatter.ipp
@@ -62,7 +62,7 @@ test_phase_identifier()
void
compiler_log_formatter::log_start( std::ostream& output, counter_t test_cases_amount )
{
- m_color_output = runtime_config::get<bool>( runtime_config::COLOR_OUTPUT );
+ m_color_output = runtime_config::get<bool>( runtime_config::btrt_color_output );
if( test_cases_amount > 0 )
output << "Running " << test_cases_amount << " test "
diff --git a/boost/test/impl/execution_monitor.ipp b/boost/test/impl/execution_monitor.ipp
index 3ddcf67137..0c5690ca89 100644
--- a/boost/test/impl/execution_monitor.ipp
+++ b/boost/test/impl/execution_monitor.ipp
@@ -32,7 +32,7 @@
#include <boost/cstdlib.hpp> // for exit codes
#include <boost/config.hpp> // for workarounds
#include <boost/core/ignore_unused.hpp> // for ignore_unused
-#ifndef BOOST_NO_EXCEPTION
+#ifndef BOOST_NO_EXCEPTIONS
#include <boost/exception/get_error_info.hpp> // for get_error_info
#include <boost/exception/current_exception_cast.hpp> // for current_exception_cast
#endif
@@ -196,7 +196,7 @@ namespace boost {
// ************** throw_exception ************** //
// ************************************************************************** //
-#ifdef BOOST_NO_EXCEPTION
+#ifdef BOOST_NO_EXCEPTIONS
void throw_exception( std::exception const & e ) { abort(); }
#endif
@@ -216,7 +216,7 @@ namespace detail {
# define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) vsnprintf( (a1), (a2), (a3), (a4) )
#endif
-#ifndef BOOST_NO_EXCEPTION
+#ifndef BOOST_NO_EXCEPTIONS
template <typename ErrorInfo>
typename ErrorInfo::value_type
@@ -1285,7 +1285,7 @@ execution_monitor::execute( boost::function<int ()> const& F )
catch( ... )
{ detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); }
-#endif // !BOOST_NO_EXCEPTION
+#endif // !BOOST_NO_EXCEPTIONS
return 0; // never reached; supplied to quiet compiler warnings
} // execute
@@ -1354,11 +1354,7 @@ unsigned
enable( unsigned mask )
{
boost::ignore_unused(mask);
-
-#if defined(UNDER_CE)
- /* Not Implemented in Windows CE */
- return BOOST_FPE_OFF;
-#elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
+#if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__)
_clearfp();
#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
@@ -1373,9 +1369,10 @@ enable( unsigned mask )
if( ::_controlfp_s( 0, old_cw & ~mask, BOOST_FPE_ALL ) != 0 )
return BOOST_FPE_INV;
#endif
-
return ~old_cw & BOOST_FPE_ALL;
-#elif defined(__GLIBC__) && defined(__USE_GNU)
+
+#elif defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)
+ // same macro definition as in execution_monitor.hpp
if (BOOST_FPE_ALL == BOOST_FPE_OFF)
/* Not Implemented */
return BOOST_FPE_OFF;
@@ -1395,12 +1392,8 @@ disable( unsigned mask )
{
boost::ignore_unused(mask);
-#if defined(UNDER_CE)
- /* Not Implemented in Windows CE */
- return BOOST_FPE_INV;
-#elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
+#if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__)
_clearfp();
-
#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
unsigned old_cw = ::_controlfp( 0, 0 );
::_controlfp( old_cw | mask, BOOST_FPE_ALL );
@@ -1413,9 +1406,9 @@ disable( unsigned mask )
if( ::_controlfp_s( 0, old_cw | mask, BOOST_FPE_ALL ) != 0 )
return BOOST_FPE_INV;
#endif
-
return ~old_cw & BOOST_FPE_ALL;
-#elif defined(__GLIBC__) && defined(__USE_GNU)
+
+#elif defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)
if (BOOST_FPE_ALL == BOOST_FPE_OFF)
/* Not Implemented */
return BOOST_FPE_INV;
diff --git a/boost/test/impl/framework.ipp b/boost/test/impl/framework.ipp
index 298dde92ea..a35e8a54ac 100644
--- a/boost/test/impl/framework.ipp
+++ b/boost/test/impl/framework.ipp
@@ -396,7 +396,7 @@ parse_filters( test_unit_id master_tu_id, test_unit_id_list& tu_to_enable, test_
// 10. collect tu to enable and disable based on filters
bool had_selector_filter = false;
- std::vector<std::string> const& filters = runtime_config::get<std::vector<std::string> >( runtime_config::RUN_FILTERS );
+ std::vector<std::string> const& filters = runtime_config::get<std::vector<std::string> >( runtime_config::btrt_run_filters );
BOOST_TEST_FOREACH( const_string, filter, filters ) {
BOOST_TEST_SETUP_ASSERT( !filter.is_empty(), "Invalid filter specification" );
@@ -552,7 +552,7 @@ public:
test_unit_id_list tu_to_disable;
// 10. If there are any filters supplied, figure out lists of test units to enable/disable
- bool had_selector_filter = !runtime_config::get<std::vector<std::string> >( runtime_config::RUN_FILTERS ).empty() &&
+ bool had_selector_filter = !runtime_config::get<std::vector<std::string> >( runtime_config::btrt_run_filters ).empty() &&
parse_filters( master_tu_id, tu_to_enable, tu_to_disable );
// 20. Set the stage: either use default run status or disable all test units
@@ -657,7 +657,7 @@ public:
if( tu.p_type == TUT_SUITE ) {
test_suite const& ts = static_cast<test_suite const&>( tu );
- if( runtime_config::get<unsigned>( runtime_config::RANDOM_SEED ) == 0 ) {
+ if( runtime_config::get<unsigned>( runtime_config::btrt_random_seed ) == 0 ) {
typedef std::pair<counter_t,test_unit_id> value_type;
BOOST_TEST_FOREACH( value_type, chld, ts.m_ranked_children ) {
@@ -845,26 +845,26 @@ setup_loggers()
BOOST_TEST_I_TRY {
#ifdef BOOST_TEST_SUPPORT_TOKEN_ITERATOR
- bool has_combined_logger = runtime_config::has( runtime_config::COMBINED_LOGGER )
- && !runtime_config::get< std::vector<std::string> >( runtime_config::COMBINED_LOGGER ).empty();
+ bool has_combined_logger = runtime_config::has( runtime_config::btrt_combined_logger )
+ && !runtime_config::get< std::vector<std::string> >( runtime_config::btrt_combined_logger ).empty();
#else
bool has_combined_logger = false;
#endif
if( !has_combined_logger ) {
- unit_test_log.set_threshold_level( runtime_config::get<log_level>( runtime_config::LOG_LEVEL ) );
- const output_format format = runtime_config::get<output_format>( runtime_config::LOG_FORMAT );
+ unit_test_log.set_threshold_level( runtime_config::get<log_level>( runtime_config::btrt_log_level ) );
+ const output_format format = runtime_config::get<output_format>( runtime_config::btrt_log_format );
unit_test_log.set_format( format );
runtime_config::stream_holder& stream_logger = s_frk_state().m_log_sinks[format];
- if( runtime_config::has( runtime_config::LOG_SINK ) )
- stream_logger.setup( runtime_config::get<std::string>( runtime_config::LOG_SINK ) );
+ if( runtime_config::has( runtime_config::btrt_log_sink ) )
+ stream_logger.setup( runtime_config::get<std::string>( runtime_config::btrt_log_sink ) );
unit_test_log.set_stream( stream_logger.ref() );
}
else
{
- const std::vector<std::string>& v_output_format = runtime_config::get< std::vector<std::string> >( runtime_config::COMBINED_LOGGER ) ;
+ const std::vector<std::string>& v_output_format = runtime_config::get< std::vector<std::string> >( runtime_config::btrt_combined_logger ) ;
static const std::pair<const char*, log_level> all_log_levels[] = {
std::make_pair( "all" , log_successful_tests ),
@@ -1033,26 +1033,26 @@ init( init_unit_test_func init_func, int argc, char* argv[] )
impl::setup_loggers();
// 30. Set the desired report level, format and sink
- results_reporter::set_level( runtime_config::get<report_level>( runtime_config::REPORT_LEVEL ) );
- results_reporter::set_format( runtime_config::get<output_format>( runtime_config::REPORT_FORMAT ) );
+ results_reporter::set_level( runtime_config::get<report_level>( runtime_config::btrt_report_level ) );
+ results_reporter::set_format( runtime_config::get<output_format>( runtime_config::btrt_report_format ) );
- if( runtime_config::has( runtime_config::REPORT_SINK ) )
- s_frk_state().m_report_sink.setup( runtime_config::get<std::string>( runtime_config::REPORT_SINK ) );
+ if( runtime_config::has( runtime_config::btrt_report_sink ) )
+ s_frk_state().m_report_sink.setup( runtime_config::get<std::string>( runtime_config::btrt_report_sink ) );
results_reporter::set_stream( s_frk_state().m_report_sink.ref() );
// 40. Register default test observers
register_observer( results_collector );
register_observer( unit_test_log );
- if( runtime_config::get<bool>( runtime_config::SHOW_PROGRESS ) ) {
+ if( runtime_config::get<bool>( runtime_config::btrt_show_progress ) ) {
progress_monitor.set_stream( std::cout ); // defaults to stdout
register_observer( progress_monitor );
}
// 50. Set up memory leak detection
- unsigned long detect_mem_leak = runtime_config::get<unsigned long>( runtime_config::DETECT_MEM_LEAKS );
+ unsigned long detect_mem_leak = runtime_config::get<unsigned long>( runtime_config::btrt_detect_mem_leaks );
if( detect_mem_leak > 0 ) {
- debug::detect_memory_leaks( true, runtime_config::get<std::string>( runtime_config::REPORT_MEM_LEAKS ) );
+ debug::detect_memory_leaks( true, runtime_config::get<std::string>( runtime_config::btrt_report_mem_leaks ) );
debug::break_memory_alloc( (long)detect_mem_leak );
}
@@ -1408,7 +1408,7 @@ run( test_unit_id id, bool continue_test )
test_case_counter tcc;
traverse_test_tree( id, tcc );
- BOOST_TEST_SETUP_ASSERT( tcc.p_count != 0 , runtime_config::get<std::vector<std::string> >( runtime_config::RUN_FILTERS ).empty()
+ BOOST_TEST_SETUP_ASSERT( tcc.p_count != 0 , runtime_config::get<std::vector<std::string> >( runtime_config::btrt_run_filters ).empty()
? BOOST_TEST_L( "test tree is empty" )
: BOOST_TEST_L( "no test cases matching filter or all test cases were disabled" ) );
@@ -1428,7 +1428,7 @@ run( test_unit_id id, bool continue_test )
}
}
- unsigned seed = runtime_config::get<unsigned>( runtime_config::RANDOM_SEED );
+ unsigned seed = runtime_config::get<unsigned>( runtime_config::btrt_random_seed );
switch( seed ) {
case 0:
break;
diff --git a/boost/test/impl/junit_log_formatter.ipp b/boost/test/impl/junit_log_formatter.ipp
index a07ee5e2b0..dd528bc903 100644
--- a/boost/test/impl/junit_log_formatter.ipp
+++ b/boost/test/impl/junit_log_formatter.ipp
@@ -90,7 +90,7 @@ junit_log_formatter::log_start( std::ostream& ostr, counter_t test_cases_amount)
{
map_tests.clear();
list_path_to_root.clear();
- root_id = INV_TEST_UNIT_ID;
+ runner_log_entry.clear();
}
//____________________________________________________________________________//
@@ -101,10 +101,12 @@ public:
std::ostream& stream,
test_unit const& ts,
junit_log_formatter::map_trace_t const& mt,
+ junit_impl::junit_log_helper const& runner_log_,
bool display_build_info )
: m_stream(stream)
, m_ts( ts )
, m_map_test( mt )
+ , runner_log( runner_log_ )
, m_id( 0 )
, m_display_build_info(display_build_info)
{ }
@@ -126,46 +128,71 @@ public:
m_stream << "</" << entry_type << ">";
}
- void visit( test_case const& tc )
+ struct conditional_cdata_helper {
+ std::ostream &ostr;
+ std::string const field;
+ bool empty;
+
+ conditional_cdata_helper(std::ostream &ostr_, std::string field_)
+ : ostr(ostr_)
+ , field(field_)
+ , empty(true)
+ {}
+
+ ~conditional_cdata_helper() {
+ if(!empty) {
+ ostr << BOOST_TEST_L( "]]>" ) << "</" << field << '>' << std::endl;
+ }
+ }
+
+ void operator()(const std::string& s) {
+ bool current_empty = s.empty();
+ if(empty) {
+ if(!current_empty) {
+ empty = false;
+ ostr << '<' << field << '>' << BOOST_TEST_L( "<![CDATA[" );
+ }
+ }
+ if(!current_empty) {
+ ostr << s;
+ }
+ }
+ };
+
+ std::list<std::string> build_skipping_chain(test_case const & tc) const
{
- test_results const& tr = results_collector.results( tc.p_id );
+ // 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);
- junit_impl::junit_log_helper detailed_log;
- bool need_skipping_reason = false;
- bool skipped = false;
+ std::list<std::string> out;
- junit_log_formatter::map_trace_t::const_iterator it_element(m_map_test.find(tc.p_id));
- if( it_element != m_map_test.end() )
- {
- detailed_log = it_element->second;
+ test_unit_id id(tc.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");
+ 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;
}
- else
+ junit_log_formatter::map_trace_t::const_iterator it_element_stack(m_map_test.find(id));
+ if( it_element_stack != m_map_test.end() )
{
- need_skipping_reason = true;
+ out.push_back("- reason: '" + it_element_stack->second.skipping_reason + "'");
+ out.push_front("Test case disabled because of the following chain of decision:\n");
}
+ return out;
+ }
+
+ std::string get_class_name(test_case const & tc) const {
std::string classname;
test_unit_id id(tc.p_parent_id);
- while( id != m_ts.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 );
-
- if(need_skipping_reason)
- {
- test_results const& tr_parent = results_collector.results( id );
- if( tr_parent.p_skipped )
- {
- skipped = true;
- detailed_log.system_out+= "- disabled: " + tu.full_name() + "\n";
- }
- junit_log_formatter::map_trace_t::const_iterator it_element_stack(m_map_test.find(id));
- if( it_element_stack != m_map_test.end() )
- {
- detailed_log.system_out+= "- skipping decision: '" + it_element_stack->second.system_out + "'";
- detailed_log.system_out = "SKIPPING decision stack:\n" + detailed_log.system_out;
- need_skipping_reason = false;
- }
- }
-
classname = tu_name_normalize(tu.p_name) + "." + classname;
id = tu.p_parent_id;
}
@@ -175,23 +202,118 @@ public:
classname.erase(classname.size()-1);
}
+ return classname;
+ }
+
+ void write_testcase_header(test_case const & tc,
+ test_results const *tr = 0) const
+ {
//
// test case header
// total number of assertions
- m_stream << "<testcase assertions" << utils::attr_value() << tr.p_assertions_passed + tr.p_assertions_failed;
+ m_stream << "<testcase assertions" << utils::attr_value() << tr->p_assertions_passed + tr->p_assertions_failed;
// class name
+ const std::string classname = get_class_name(tc);
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)
- << " time" << utils::attr_value() << double(tr.p_duration_microseconds) * 1E-6
+ << " time" << utils::attr_value() << double(tr->p_duration_microseconds) * 1E-6
<< ">" << std::endl;
+ }
- if( tr.p_skipped || skipped ) {
+ 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
+ {
+ // 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());
+ it != ite;
+ ++it)
+ {
+ system_out_helper(*it);
+ }
+ }
+
+ // stdout
+ for(std::list<std::string>::const_iterator it(detailed_log.system_out.begin()), ite(detailed_log.system_out.end());
+ it != ite;
+ ++it)
+ {
+ system_out_helper(*it);
+ }
+
+ // warning/info message last
+ for(std::vector< junit_impl::junit_log_helper::assertion_entry >::const_iterator 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)
+ 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
+ {
+ // system-err output + test case informations
+ bool has_failed = (tr != 0) ? !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;
+ }
+ else {
+ 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(!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());
+ it != ite;
+ ++it)
+ {
+ system_err_helper(*it);
+ }
+
+ if(!detailed_log.system_err.empty())
+ o << std::endl << "STDERR END ------------" << std::endl;
+ }
+ }
+
+ void output_detailed_logs(junit_impl::junit_log_helper const &detailed_log,
+ test_case const & tc,
+ bool skipped,
+ test_results const *tr = 0) const
+ {
+ write_testcase_header(tc, tr);
+
+ if( skipped ) {
m_stream << "<skipped/>" << std::endl;
}
else {
@@ -209,45 +331,24 @@ public:
}
}
- // system-out + all info/messages
- std::string system_out = detailed_log.system_out;
- for(std::vector< junit_impl::junit_log_helper::assertion_entry >::const_iterator 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)
- continue;
- system_out += it->output;
- }
+ write_testcase_system_out(detailed_log, &tc, skipped, tr);
+ write_testcase_system_err(detailed_log, &tc, tr);
+ m_stream << "</testcase>" << std::endl;
+ }
- if(!system_out.empty()) {
- m_stream
- << "<system-out>"
- << utils::cdata() << system_out
- << "</system-out>"
- << std::endl;
- }
+ void visit( test_case const& tc )
+ {
- // system-err output + test case informations
- std::string system_err = detailed_log.system_err;
+ test_results const& tr = results_collector.results( tc.p_id );
+ junit_log_formatter::map_trace_t::const_iterator it_find = m_map_test.find(tc.p_id);
+ if(it_find == m_map_test.end())
{
- // test case information (redundant but useful)
- std::ostringstream o;
- o << "Test case:" << std::endl
- << "- name: " << tc.full_name() << std::endl
- << "- description: '" << tc.p_description << "'" << std::endl
- << "- file: " << file_basename(tc.p_file_name) << std::endl
- << "- line: " << tc.p_line_num << std::endl
- ;
- system_err = o.str() + system_err;
+ // test has been skipped and not seen by the logger
+ output_detailed_logs(junit_impl::junit_log_helper(), tc, true, &tr);
+ }
+ else {
+ output_detailed_logs(it_find->second, tc, tr.p_skipped, &tr);
}
- m_stream
- << "<system-err>"
- << utils::cdata() << system_err
- << "</system-err>"
- << std::endl;
-
- m_stream << "</testcase>" << std::endl;
}
bool test_suite_start( test_suite const& ts )
@@ -257,8 +358,6 @@ public:
return true;
test_results const& tr = results_collector.results( ts.p_id );
-
- m_stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
m_stream << "<testsuite";
m_stream
@@ -292,6 +391,10 @@ public:
{
if( m_ts.p_id != ts.p_id )
return;
+
+ write_testcase_system_out(runner_log, 0, false, 0);
+ write_testcase_system_err(runner_log, 0, 0);
+
m_stream << "</testsuite>";
}
@@ -300,6 +403,7 @@ private:
std::ostream& m_stream;
test_unit const& m_ts;
junit_log_formatter::map_trace_t const& m_map_test;
+ junit_impl::junit_log_helper const& runner_log;
size_t m_id;
bool m_display_build_info;
};
@@ -309,9 +413,26 @@ private:
void
junit_log_formatter::log_finish( std::ostream& ostr )
{
- junit_result_helper ch( ostr, boost::unit_test::framework::get( root_id, TUT_SUITE ), map_tests, m_display_build_info );
- traverse_test_tree( root_id, ch, true ); // last is to ignore disabled suite special handling
+ ostr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
+
+ // getting the root test suite
+ if(!map_tests.empty()) {
+ test_unit* root = &boost::unit_test::framework::get( map_tests.begin()->first, TUT_ANY );
+ // looking for the root of the SUBtree (we stay in the subtree)
+ while(root->p_parent_id != INV_TEST_UNIT_ID && map_tests.count(root->p_parent_id) > 0) {
+ root = &boost::unit_test::framework::get( root->p_parent_id, TUT_ANY );
+ }
+ junit_result_helper ch( ostr, *root, map_tests, this->runner_log_entry, m_display_build_info );
+ traverse_test_tree( root->p_id, ch, true ); // last is to ignore disabled suite special handling
+ }
+ else {
+ ostr << "<testsuites errors=\"1\">";
+ ostr << "<testsuite errors=\"1\" name=\"boost-test-framework\">";
+ ostr << "<testcase assertions=\"1\" name=\"test-setup\">";
+ ostr << "<system-out>Incorrect setup: no test case executed</system-out>";
+ ostr << "</testcase></testsuite></testsuites>";
+ }
return;
}
@@ -328,8 +449,6 @@ junit_log_formatter::log_build_info( std::ostream& ostr )
void
junit_log_formatter::test_unit_start( std::ostream& ostr, test_unit const& tu )
{
- if(list_path_to_root.empty())
- root_id = tu.p_id;
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
}
@@ -358,16 +477,11 @@ 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 )
{
- if(tu.p_type == TUT_CASE)
- {
- junit_impl::junit_log_helper& v = map_tests[tu.p_id];
- v.system_out.assign(reason.begin(), reason.end());
- }
- else
- {
- junit_impl::junit_log_helper& v = map_tests[tu.p_id];
- v.system_out.assign(reason.begin(), reason.end());
- }
+ // 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.
+ // The "skip" boolean is given by the boost.test framework
+ junit_impl::junit_log_helper& v = map_tests[tu.p_id]; // not sure if we can use get_current_log_entry()
+ v.skipping_reason.assign(reason.begin(), reason.end());
}
//____________________________________________________________________________//
@@ -380,67 +494,62 @@ junit_log_formatter::log_exception_start( std::ostream& ostr, log_checkpoint_dat
m_is_last_assertion_or_error = false;
- if(!list_path_to_root.empty())
- {
- junit_impl::junit_log_helper& last_entry = map_tests[list_path_to_root.back()];
-
- junit_impl::junit_log_helper::assertion_entry entry;
+ junit_impl::junit_log_helper& last_entry = get_current_log_entry();
- entry.logentry_message = "unexpected exception";
- entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_error;
+ junit_impl::junit_log_helper::assertion_entry entry;
- switch(ex.code())
- {
- case execution_exception::cpp_exception_error:
- entry.logentry_type = "uncaught exception";
- break;
- case execution_exception::timeout_error:
- entry.logentry_type = "execution timeout";
- break;
- case execution_exception::user_error:
- entry.logentry_type = "user, assert() or CRT error";
- break;
- case execution_exception::user_fatal_error:
- // Looks like never used
- entry.logentry_type = "user fatal error";
- break;
- case execution_exception::system_error:
- entry.logentry_type = "system error";
- break;
- case execution_exception::system_fatal_error:
- entry.logentry_type = "system fatal error";
- break;
- default:
- entry.logentry_type = "no error"; // not sure how to handle this one
- break;
- }
+ entry.logentry_message = "unexpected exception";
+ entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_error;
- o << "UNCAUGHT EXCEPTION:" << std::endl;
- if( !loc.m_function.is_empty() )
- o << "- function: \"" << loc.m_function << "\"" << std::endl;
-
- o << "- file: " << file_basename(loc.m_file_name) << std::endl
- << "- line: " << loc.m_line_num << std::endl
- << std::endl;
+ switch(ex.code())
+ {
+ case execution_exception::cpp_exception_error:
+ entry.logentry_type = "uncaught exception";
+ break;
+ case execution_exception::timeout_error:
+ entry.logentry_type = "execution timeout";
+ break;
+ case execution_exception::user_error:
+ entry.logentry_type = "user, assert() or CRT error";
+ break;
+ case execution_exception::user_fatal_error:
+ // Looks like never used
+ entry.logentry_type = "user fatal error";
+ break;
+ case execution_exception::system_error:
+ entry.logentry_type = "system error";
+ break;
+ case execution_exception::system_fatal_error:
+ entry.logentry_type = "system fatal error";
+ break;
+ default:
+ entry.logentry_type = "no error"; // not sure how to handle this one
+ break;
+ }
- o << "\nEXCEPTION STACK TRACE: --------------\n" << ex.what()
- << "\n-------------------------------------";
+ o << "UNCAUGHT EXCEPTION:" << std::endl;
+ if( !loc.m_function.is_empty() )
+ o << "- function: \"" << loc.m_function << "\"" << std::endl;
- if( !checkpoint_data.m_file_name.is_empty() ) {
- o << std::endl << std::endl
- << "Last checkpoint:" << std::endl
- << "- message: \"" << checkpoint_data.m_message << "\"" << std::endl
- << "- file: " << file_basename(checkpoint_data.m_file_name) << std::endl
- << "- line: " << checkpoint_data.m_line_num << std::endl
- ;
- }
+ o << "- file: " << file_basename(loc.m_file_name) << std::endl
+ << "- line: " << loc.m_line_num << std::endl
+ << std::endl;
- entry.output = o.str();
+ o << "\nEXCEPTION STACK TRACE: --------------\n" << ex.what()
+ << "\n-------------------------------------";
- last_entry.assertion_entries.push_back(entry);
+ if( !checkpoint_data.m_file_name.is_empty() ) {
+ o << std::endl << std::endl
+ << "Last checkpoint:" << std::endl
+ << "- message: \"" << checkpoint_data.m_message << "\"" << std::endl
+ << "- file: " << file_basename(checkpoint_data.m_file_name) << std::endl
+ << "- line: " << checkpoint_data.m_line_num << std::endl
+ ;
}
- // check what to do with this one
+ entry.output = o.str();
+
+ last_entry.assertion_entries.push_back(entry);
}
//____________________________________________________________________________//
@@ -449,8 +558,8 @@ void
junit_log_formatter::log_exception_finish( std::ostream& ostr )
{
// sealing the last entry
- assert(!map_tests[list_path_to_root.back()].assertion_entries.back().sealed);
- map_tests[list_path_to_root.back()].assertion_entries.back().sealed = true;
+ assert(!get_current_log_entry().assertion_entries.back().sealed);
+ get_current_log_entry().assertion_entries.back().sealed = true;
}
//____________________________________________________________________________//
@@ -458,17 +567,36 @@ 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_impl::junit_log_helper& last_entry = map_tests[list_path_to_root.back()];
+ junit_impl::junit_log_helper& last_entry = get_current_log_entry();
+ last_entry.skipping = false;
m_is_last_assertion_or_error = true;
switch(let)
{
case unit_test_log_formatter::BOOST_UTL_ET_INFO:
+ {
+ if(m_log_level_internal > log_successful_tests) {
+ last_entry.skipping = true;
+ break;
+ }
+ // no break on purpose
+ }
case unit_test_log_formatter::BOOST_UTL_ET_MESSAGE:
+ {
+ if(m_log_level_internal > log_messages) {
+ last_entry.skipping = true;
+ break;
+ }
+ // no break on purpose
+ }
case unit_test_log_formatter::BOOST_UTL_ET_WARNING:
{
+ if(m_log_level_internal > log_warnings) {
+ last_entry.skipping = true;
+ break;
+ }
std::ostringstream o;
-
junit_impl::junit_log_helper::assertion_entry entry;
+
entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_info;
entry.logentry_message = "info";
entry.logentry_type = "message";
@@ -505,22 +633,18 @@ junit_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const&
break;
}
}
-
}
- //____________________________________________________________________________//
-
-
-
//____________________________________________________________________________//
void
junit_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
{
- assert(map_tests[list_path_to_root.back()].assertion_entries.empty() || !map_tests[list_path_to_root.back()].assertion_entries.back().sealed);
- junit_impl::junit_log_helper& last_entry = map_tests[list_path_to_root.back()];
- std::ostringstream o;
- utils::print_escaped_cdata( o, value );
+ junit_impl::junit_log_helper& last_entry = get_current_log_entry();
+ if(last_entry.skipping)
+ return;
+
+ assert(last_entry.assertion_entries.empty() || !last_entry.assertion_entries.back().sealed);
if(!last_entry.assertion_entries.empty())
{
@@ -531,7 +655,7 @@ junit_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
{
// this may be a message coming from another observer
// the prefix is set in the log_entry_start
- last_entry.system_out += value;
+ last_entry.system_out.push_back(std::string(value.begin(), value.end()));
}
}
@@ -540,16 +664,22 @@ junit_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
void
junit_log_formatter::log_entry_finish( std::ostream& ostr )
{
- assert(map_tests[list_path_to_root.back()].assertion_entries.empty() || !map_tests[list_path_to_root.back()].assertion_entries.back().sealed);
- junit_impl::junit_log_helper& last_entry = map_tests[list_path_to_root.back()];
- if(!last_entry.assertion_entries.empty()) {
- junit_impl::junit_log_helper::assertion_entry& log_entry = last_entry.assertion_entries.back();
- log_entry.output += "\n\n"; // quote end, CR
- log_entry.sealed = true;
- }
- else {
- last_entry.system_out += "\n\n"; // quote end, CR
+ junit_impl::junit_log_helper& last_entry = get_current_log_entry();
+ if(!last_entry.skipping)
+ {
+ assert(last_entry.assertion_entries.empty() || !last_entry.assertion_entries.back().sealed);
+
+ if(!last_entry.assertion_entries.empty()) {
+ junit_impl::junit_log_helper::assertion_entry& log_entry = last_entry.assertion_entries.back();
+ log_entry.output += "\n\n"; // quote end, CR
+ log_entry.sealed = true;
+ }
+ else {
+ last_entry.system_out.push_back("\n\n"); // quote end, CR
+ }
}
+
+ last_entry.skipping = false;
}
//____________________________________________________________________________//
@@ -557,16 +687,21 @@ junit_log_formatter::log_entry_finish( std::ostream& ostr )
void
junit_log_formatter::entry_context_start( std::ostream& ostr, log_level )
{
- std::vector< junit_impl::junit_log_helper::assertion_entry > &v_failure_or_error = map_tests[list_path_to_root.back()].assertion_entries;
+ junit_impl::junit_log_helper& last_entry = get_current_log_entry();
+ if(last_entry.skipping)
+ return;
+
+ std::vector< junit_impl::junit_log_helper::assertion_entry > &v_failure_or_error = last_entry.assertion_entries;
assert(!v_failure_or_error.back().sealed);
+ junit_impl::junit_log_helper::assertion_entry& last_log_entry = v_failure_or_error.back();
if(m_is_last_assertion_or_error)
{
- v_failure_or_error.back().output += "\n- context:\n";
+ last_log_entry.output += "\n- context:\n";
}
else
{
- v_failure_or_error.back().output += "\n\nCONTEXT:\n";
+ last_log_entry.output += "\n\nCONTEXT:\n";
}
}
@@ -576,7 +711,10 @@ void
junit_log_formatter::entry_context_finish( std::ostream& ostr )
{
// no op, may be removed
- assert(!map_tests[list_path_to_root.back()].assertion_entries.back().sealed);
+ junit_impl::junit_log_helper& last_entry = get_current_log_entry();
+ if(last_entry.skipping)
+ return;
+ assert(!get_current_log_entry().assertion_entries.back().sealed);
}
//____________________________________________________________________________//
@@ -584,8 +722,15 @@ junit_log_formatter::entry_context_finish( std::ostream& ostr )
void
junit_log_formatter::log_entry_context( std::ostream& ostr, const_string context_descr )
{
- assert(!map_tests[list_path_to_root.back()].assertion_entries.back().sealed);
- map_tests[list_path_to_root.back()].assertion_entries.back().output += (m_is_last_assertion_or_error ? " - '": "- '") + std::string(context_descr.begin(), context_descr.end()) + "'\n"; // quote end
+ junit_impl::junit_log_helper& last_entry = get_current_log_entry();
+ if(last_entry.skipping)
+ return;
+
+ assert(!last_entry.assertion_entries.back().sealed);
+ junit_impl::junit_log_helper::assertion_entry& last_log_entry = get_current_log_entry().assertion_entries.back();
+
+ last_log_entry.output +=
+ (m_is_last_assertion_or_error ? " - '": "- '") + std::string(context_descr.begin(), context_descr.end()) + "'\n"; // quote end
}
//____________________________________________________________________________//
diff --git a/boost/test/impl/plain_report_formatter.ipp b/boost/test/impl/plain_report_formatter.ipp
index 262083eeaa..cbf5a4c029 100644
--- a/boost/test/impl/plain_report_formatter.ipp
+++ b/boost/test/impl/plain_report_formatter.ipp
@@ -83,7 +83,7 @@ void
plain_report_formatter::results_report_start( std::ostream& ostr )
{
m_indent = 0;
- m_color_output = runtime_config::get<bool>( runtime_config::COLOR_OUTPUT );
+ m_color_output = runtime_config::get<bool>( runtime_config::btrt_color_output );
ostr << '\n';
}
diff --git a/boost/test/impl/progress_monitor.ipp b/boost/test/impl/progress_monitor.ipp
index 7fb3baf8f0..34149745cf 100644
--- a/boost/test/impl/progress_monitor.ipp
+++ b/boost/test/impl/progress_monitor.ipp
@@ -124,7 +124,7 @@ progress_monitor_impl& s_pm_impl() { static progress_monitor_impl the_inst; retu
void
progress_monitor_t::test_start( counter_t test_cases_amount )
{
- s_pm_impl().m_color_output = runtime_config::get<bool>( runtime_config::COLOR_OUTPUT );
+ s_pm_impl().m_color_output = runtime_config::get<bool>( runtime_config::btrt_color_output );
PM_SCOPED_COLOR();
diff --git a/boost/test/impl/test_tools.ipp b/boost/test/impl/test_tools.ipp
index a6b20a7729..853b3913ee 100644
--- a/boost/test/impl/test_tools.ipp
+++ b/boost/test/impl/test_tools.ipp
@@ -68,6 +68,12 @@ namespace tt_detail {
// ************************************************************************** //
void
+print_log_value<bool>::operator()( std::ostream& ostr, bool t )
+{
+ ostr << std::boolalpha << t;
+}
+
+void
print_log_value<char>::operator()( std::ostream& ostr, char t )
{
if( (std::isprint)( static_cast<unsigned char>(t) ) )
@@ -113,6 +119,14 @@ print_log_value<wchar_t const*>::operator()( std::ostream& ostr, wchar_t const*
ostr << ( t ? t : L"null string" );
}
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+void
+print_log_value<std::nullptr_t>::operator()( std::ostream& ostr, std::nullptr_t p )
+{
+ ostr << "nullptr";
+}
+#endif
+
//____________________________________________________________________________//
// ************************************************************************** //
diff --git a/boost/test/impl/unit_test_log.ipp b/boost/test/impl/unit_test_log.ipp
index 5f3fa6510d..c52260b94b 100644
--- a/boost/test/impl/unit_test_log.ipp
+++ b/boost/test/impl/unit_test_log.ipp
@@ -168,7 +168,7 @@ unit_test_log_t::test_start( counter_t test_cases_amount )
current_logger_data.m_log_formatter->log_start( current_logger_data.stream(), test_cases_amount );
- if( runtime_config::get<bool>( runtime_config::BUILD_INFO ) )
+ 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.m_entry_in_progress = false;
@@ -442,8 +442,11 @@ unit_test_log_t&
unit_test_log_t::operator<<( lazy_ostream const& value )
{
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 && s_log_impl().m_entry_data.m_level >= current_logger_data.get_log_level() && !value.empty() && log_entry_start(current_logger_data.m_format) )
- current_logger_data.m_log_formatter->log_entry_value( current_logger_data.stream(), value );
+ if( current_logger_data.m_enabled && s_log_impl().m_entry_data.m_level >= current_logger_data.get_log_level() && !value.empty() ) {
+ if( log_entry_start(current_logger_data.m_format) ) {
+ current_logger_data.m_log_formatter->log_entry_value( current_logger_data.stream(), value );
+ }
+ }
}
return *this;
}
diff --git a/boost/test/impl/unit_test_main.ipp b/boost/test/impl/unit_test_main.ipp
index db61930652..dabe328c8c 100644
--- a/boost/test/impl/unit_test_main.ipp
+++ b/boost/test/impl/unit_test_main.ipp
@@ -188,7 +188,7 @@ unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
BOOST_TEST_I_TRY {
framework::init( init_func, argc, argv );
- if( runtime_config::get<bool>( runtime_config::WAIT_FOR_DEBUGGER ) ) {
+ if( runtime_config::get<bool>( runtime_config::btrt_wait_for_debugger ) ) {
results_reporter::get_stream() << "Press any key to continue..." << std::endl;
// getchar is defined as a macro in uClibc. Use parenthesis to fix
@@ -199,7 +199,7 @@ unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
framework::finalize_setup_phase();
- output_format list_cont = runtime_config::get<output_format>( runtime_config::LIST_CONTENT );
+ output_format list_cont = runtime_config::get<output_format>( runtime_config::btrt_list_content );
if( list_cont != unit_test::OF_INVALID ) {
if( list_cont == unit_test::OF_DOT ) {
ut_detail::dot_content_reporter reporter( results_reporter::get_stream() );
@@ -215,7 +215,7 @@ unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
return boost::exit_success;
}
- if( runtime_config::get<bool>( runtime_config::LIST_LABELS ) ) {
+ if( runtime_config::get<bool>( runtime_config::btrt_list_labels ) ) {
ut_detail::labels_collector collector;
traverse_test_tree( framework::master_test_suite().p_id, collector, true );
@@ -232,7 +232,7 @@ unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
results_reporter::make_report();
- result_code = !runtime_config::get<bool>( runtime_config::RESULT_CODE )
+ result_code = !runtime_config::get<bool>( runtime_config::btrt_result_code )
? boost::exit_success
: results_collector.results( framework::master_test_suite().p_id ).result_code();
}
diff --git a/boost/test/impl/unit_test_monitor.ipp b/boost/test/impl/unit_test_monitor.ipp
index 304c8f1c04..fdd36f7c3a 100644
--- a/boost/test/impl/unit_test_monitor.ipp
+++ b/boost/test/impl/unit_test_monitor.ipp
@@ -37,11 +37,11 @@ unit_test_monitor_t::error_level
unit_test_monitor_t::execute_and_translate( boost::function<void ()> const& func, unsigned timeout )
{
BOOST_TEST_I_TRY {
- p_catch_system_errors.value = runtime_config::get<bool>( runtime_config::CATCH_SYS_ERRORS );
+ p_catch_system_errors.value = runtime_config::get<bool>( runtime_config::btrt_catch_sys_errors );
p_timeout.value = timeout;
- p_auto_start_dbg.value = runtime_config::get<bool>( runtime_config::AUTO_START_DBG );
- p_use_alt_stack.value = runtime_config::get<bool>( runtime_config::USE_ALT_STACK );
- p_detect_fp_exceptions.value = runtime_config::get<bool>( runtime_config::DETECT_FP_EXCEPT );
+ p_auto_start_dbg.value = runtime_config::get<bool>( runtime_config::btrt_auto_start_dbg );
+ p_use_alt_stack.value = runtime_config::get<bool>( runtime_config::btrt_use_alt_stack );
+ p_detect_fp_exceptions.value = runtime_config::get<bool>( runtime_config::btrt_detect_fp_except );
vexecute( func );
}
diff --git a/boost/test/impl/unit_test_parameters.ipp b/boost/test/impl/unit_test_parameters.ipp
index 315942e6c0..b825c46d6a 100644
--- a/boost/test/impl/unit_test_parameters.ipp
+++ b/boost/test/impl/unit_test_parameters.ipp
@@ -71,35 +71,35 @@ namespace rt = boost::runtime;
namespace runtime_config {
// UTF parameters
-std::string AUTO_START_DBG = "auto_start_dbg";
-std::string BREAK_EXEC_PATH = "break_exec_path";
-std::string BUILD_INFO = "build_info";
-std::string CATCH_SYS_ERRORS = "catch_system_errors";
-std::string COLOR_OUTPUT = "color_output";
-std::string DETECT_FP_EXCEPT = "detect_fp_exceptions";
-std::string DETECT_MEM_LEAKS = "detect_memory_leaks";
-std::string LIST_CONTENT = "list_content";
-std::string LIST_LABELS = "list_labels";
-std::string LOG_FORMAT = "log_format";
-std::string LOG_LEVEL = "log_level";
-std::string LOG_SINK = "log_sink";
-std::string COMBINED_LOGGER = "logger";
-std::string OUTPUT_FORMAT = "output_format";
-std::string RANDOM_SEED = "random";
-std::string REPORT_FORMAT = "report_format";
-std::string REPORT_LEVEL = "report_level";
-std::string REPORT_MEM_LEAKS = "report_memory_leaks_to";
-std::string REPORT_SINK = "report_sink";
-std::string RESULT_CODE = "result_code";
-std::string RUN_FILTERS = "run_test";
-std::string SAVE_TEST_PATTERN = "save_pattern";
-std::string SHOW_PROGRESS = "show_progress";
-std::string USE_ALT_STACK = "use_alt_stack";
-std::string WAIT_FOR_DEBUGGER = "wait_for_debugger";
-
-std::string HELP = "help";
-std::string USAGE = "usage";
-std::string VERSION = "version";
+std::string btrt_auto_start_dbg = "auto_start_dbg";
+std::string btrt_break_exec_path = "break_exec_path";
+std::string btrt_build_info = "build_info";
+std::string btrt_catch_sys_errors = "catch_system_errors";
+std::string btrt_color_output = "color_output";
+std::string btrt_detect_fp_except = "detect_fp_exceptions";
+std::string btrt_detect_mem_leaks = "detect_memory_leaks";
+std::string btrt_list_content = "list_content";
+std::string btrt_list_labels = "list_labels";
+std::string btrt_log_format = "log_format";
+std::string btrt_log_level = "log_level";
+std::string btrt_log_sink = "log_sink";
+std::string btrt_combined_logger = "logger";
+std::string btrt_output_format = "output_format";
+std::string btrt_random_seed = "random";
+std::string btrt_report_format = "report_format";
+std::string btrt_report_level = "report_level";
+std::string btrt_report_mem_leaks = "report_memory_leaks_to";
+std::string btrt_report_sink = "report_sink";
+std::string btrt_result_code = "result_code";
+std::string btrt_run_filters = "run_test";
+std::string btrt_save_test_pattern = "save_pattern";
+std::string btrt_show_progress = "show_progress";
+std::string btrt_use_alt_stack = "use_alt_stack";
+std::string btrt_wait_for_debugger = "wait_for_debugger";
+
+std::string btrt_help = "help";
+std::string btrt_usage = "usage";
+std::string btrt_version = "version";
//____________________________________________________________________________//
@@ -108,11 +108,11 @@ namespace {
void
register_parameters( rt::parameters_store& store )
{
- rt::option auto_start_dbg( AUTO_START_DBG, (
+ rt::option auto_start_dbg( btrt_auto_start_dbg, (
rt::description = "Automatically attaches debugger in case of system level failure (signal).",
rt::env_var = "BOOST_TEST_AUTO_START_DBG",
- rt::help = "Option " + AUTO_START_DBG + " specifies whether Boost.Test should attempt "
+ rt::help = "Option " + btrt_auto_start_dbg + " specifies whether Boost.Test should attempt "
"to attach a debugger when fatal system error occurs. At the moment this feature "
"is only available on a few selected platforms: Win32 and *nix. There is a "
"default debugger configured for these platforms. You can manually configure "
@@ -120,13 +120,13 @@ register_parameters( rt::parameters_store& store )
"Boost.Test debug API, specifically the function boost::debug::set_debugger."
));
- auto_start_dbg.add_cla_id( "--", AUTO_START_DBG, "=" );
+ auto_start_dbg.add_cla_id( "--", btrt_auto_start_dbg, "=" );
auto_start_dbg.add_cla_id( "-", "d", " " );
store.add( auto_start_dbg );
///////////////////////////////////////////////
- rt::parameter<std::string> break_exec_path( BREAK_EXEC_PATH, (
+ rt::parameter<std::string> break_exec_path( btrt_break_exec_path, (
rt::description = "For the exception safety testing allows to break at specific execution path.",
rt::env_var = "BOOST_TEST_BREAK_EXEC_PATH"
#ifndef BOOST_NO_CXX11_LAMBDAS
@@ -137,25 +137,25 @@ register_parameters( rt::parameters_store& store )
#endif
));
- break_exec_path.add_cla_id( "--", BREAK_EXEC_PATH, "=" );
+ break_exec_path.add_cla_id( "--", btrt_break_exec_path, "=" );
store.add( break_exec_path );
///////////////////////////////////////////////
- rt::option build_info( BUILD_INFO, (
+ rt::option build_info( btrt_build_info, (
rt::description = "Displays library build information.",
rt::env_var = "BOOST_TEST_BUILD_INFO",
- rt::help = "Option " + BUILD_INFO + " displays library build information, including: platform, "
+ rt::help = "Option " + btrt_build_info + " displays library build information, including: platform, "
"compiler, STL version and Boost version."
));
- build_info.add_cla_id( "--", BUILD_INFO, "=" );
+ build_info.add_cla_id( "--", btrt_build_info, "=" );
build_info.add_cla_id( "-", "i", " " );
store.add( build_info );
///////////////////////////////////////////////
- rt::option catch_sys_errors( CATCH_SYS_ERRORS, (
+ rt::option catch_sys_errors( btrt_catch_sys_errors, (
rt::description = "Allows to switch between catching and ignoring system errors (signals).",
rt::env_var = "BOOST_TEST_CATCH_SYSTEM_ERRORS",
rt::default_value =
@@ -164,7 +164,7 @@ register_parameters( rt::parameters_store& store )
#else
true,
#endif
- rt::help = "If option " + CATCH_SYS_ERRORS + " has value no the frameworks does not attempt to catch "
+ rt::help = "If option " + btrt_catch_sys_errors + " has value no the frameworks does not attempt to catch "
"asynchronous system failure events (signals on *NIX platforms or structured exceptions on Windows). "
" Default value is "
#ifdef BOOST_TEST_DEFAULTS_TO_CORE_DUMP
@@ -174,13 +174,13 @@ register_parameters( rt::parameters_store& store )
#endif
));
- catch_sys_errors.add_cla_id( "--", CATCH_SYS_ERRORS, "=", true );
+ catch_sys_errors.add_cla_id( "--", btrt_catch_sys_errors, "=", true );
catch_sys_errors.add_cla_id( "-", "s", " " );
store.add( catch_sys_errors );
///////////////////////////////////////////////
- rt::option color_output( COLOR_OUTPUT, (
+ rt::option color_output( btrt_color_output, (
rt::description = "Enables color output of the framework log and report messages.",
rt::env_var = "BOOST_TEST_COLOR_OUTPUT",
rt::help = "The framework is able to produce color output on systems which supports it. "
@@ -188,31 +188,31 @@ register_parameters( rt::parameters_store& store )
"does not produces color output."
));
- color_output.add_cla_id( "--", COLOR_OUTPUT, "=", true );
+ color_output.add_cla_id( "--", btrt_color_output, "=", true );
color_output.add_cla_id( "-", "x", " " );
store.add( color_output );
///////////////////////////////////////////////
- rt::option detect_fp_except( DETECT_FP_EXCEPT, (
+ rt::option detect_fp_except( btrt_detect_fp_except, (
rt::description = "Enables/disables floating point exceptions traps.",
rt::env_var = "BOOST_TEST_DETECT_FP_EXCEPTIONS",
- rt::help = "Option " + DETECT_FP_EXCEPT + " enables/disables hardware traps for the floating "
+ rt::help = "Option " + btrt_detect_fp_except + " enables/disables hardware traps for the floating "
"point exceptions (if supported on your platfrom)."
));
- detect_fp_except.add_cla_id( "--", DETECT_FP_EXCEPT, "=", true );
+ detect_fp_except.add_cla_id( "--", btrt_detect_fp_except, "=", true );
store.add( detect_fp_except );
///////////////////////////////////////////////
- rt::parameter<unsigned long> detect_mem_leaks( DETECT_MEM_LEAKS, (
+ rt::parameter<unsigned long> detect_mem_leaks( btrt_detect_mem_leaks, (
rt::description = "Turns on/off memory leaks detection (optionally breaking on specified alloc order number).",
rt::env_var = "BOOST_TEST_DETECT_MEMORY_LEAK",
rt::default_value = 1L,
rt::optional_value = 1L,
rt::value_hint = "<alloc order number>",
- rt::help = "Parameter " + DETECT_MEM_LEAKS + " enables/disables memory leaks detection. "
+ rt::help = "Parameter " + btrt_detect_mem_leaks + " enables/disables memory leaks detection. "
"This parameter has optional long integer value. The default value is 1, which "
"enables the memory leak detection. The value 0 disables memory leak detection. "
"Any value N greater than 1 is treated as leak allocation number and tells the "
@@ -220,12 +220,12 @@ register_parameters( rt::parameters_store& store )
"omitted the default value is assumed."
));
- detect_mem_leaks.add_cla_id( "--", DETECT_MEM_LEAKS, "=" );
+ detect_mem_leaks.add_cla_id( "--", btrt_detect_mem_leaks, "=" );
store.add( detect_mem_leaks );
///////////////////////////////////////////////
- rt::enum_parameter<unit_test::output_format> list_content( LIST_CONTENT, (
+ rt::enum_parameter<unit_test::output_format> list_content( btrt_list_content, (
rt::description = "Lists the content of test tree - names of all test suites and test cases.",
rt::env_var = "BOOST_TEST_LIST_CONTENT",
rt::default_value = OF_INVALID,
@@ -242,30 +242,30 @@ register_parameters( rt::parameters_store& store )
( "DOT", OF_DOT )
,
#endif
- rt::help = "Parameter " + LIST_CONTENT + " instructs the framework to list the content "
+ rt::help = "Parameter " + btrt_list_content + " instructs the framework to list the content "
"of the test module instead of executing the test cases. Parameter accepts "
"optional string value indicating the format of the output. Currently the "
"framework supports two formats: human readable format (HRF) and dot graph "
"format (DOT). If value is omitted HRF value is assumed."
));
- list_content.add_cla_id( "--", LIST_CONTENT, "=" );
+ list_content.add_cla_id( "--", btrt_list_content, "=" );
store.add( list_content );
///////////////////////////////////////////////
- rt::option list_labels( LIST_LABELS, (
+ rt::option list_labels( btrt_list_labels, (
rt::description = "Lists all available labels.",
rt::env_var = "BOOST_TEST_LIST_LABELS",
- rt::help = "Option " + LIST_LABELS + " instructs the framework to list all the the labels "
+ rt::help = "Option " + btrt_list_labels + " instructs the framework to list all the the labels "
"defined in the test module instead of executing the test cases."
));
- list_labels.add_cla_id( "--", LIST_LABELS, "=" );
+ list_labels.add_cla_id( "--", btrt_list_labels, "=" );
store.add( list_labels );
///////////////////////////////////////////////
- rt::enum_parameter<unit_test::output_format> log_format( LOG_FORMAT, (
+ rt::enum_parameter<unit_test::output_format> log_format( btrt_log_format, (
rt::description = "Specifies log format.",
rt::env_var = "BOOST_TEST_LOG_FORMAT",
rt::default_value = OF_CLF,
@@ -285,7 +285,7 @@ register_parameters( rt::parameters_store& store )
( "JUNIT", OF_JUNIT )
,
#endif
- rt::help = "Parameter " + LOG_FORMAT + " allows to set the frameowrk's log format to one "
+ rt::help = "Parameter " + btrt_log_format + " allows to set the frameowrk's log format to one "
"of the formats supplied by the framework. The only acceptable values for this "
"parameter are the names of the output formats supplied by the framework. By "
"default the framework uses human readable format (HRF) for testing log. This "
@@ -293,13 +293,13 @@ register_parameters( rt::parameters_store& store )
"or JUNIT as log format, which are easier to process by testing automation tools."
));
- log_format.add_cla_id( "--", LOG_FORMAT, "=" );
+ log_format.add_cla_id( "--", btrt_log_format, "=" );
log_format.add_cla_id( "-", "f", " " );
store.add( log_format );
///////////////////////////////////////////////
- rt::enum_parameter<unit_test::log_level> log_level( LOG_LEVEL, (
+ rt::enum_parameter<unit_test::log_level> log_level( btrt_log_level, (
rt::description = "Specifies log level.",
rt::env_var = "BOOST_TEST_LOG_LEVEL",
rt::default_value = log_all_errors,
@@ -333,7 +333,7 @@ register_parameters( rt::parameters_store& store )
( "nothing" , log_nothing )
,
#endif
- rt::help = "Parameter " + LOG_LEVEL + " allows to set the framework's log level. "
+ rt::help = "Parameter " + btrt_log_level + " allows to set the framework's log level. "
"Log level defines the verbosity of testing log produced by a testing "
"module. The verbosity ranges from a complete log, when all assertions "
"(both successful and failing) are reported, all notifications about "
@@ -341,29 +341,29 @@ register_parameters( rt::parameters_store& store )
"is reported to a testing log stream."
));
- log_level.add_cla_id( "--", LOG_LEVEL, "=" );
+ log_level.add_cla_id( "--", btrt_log_level, "=" );
log_level.add_cla_id( "-", "l", " " );
store.add( log_level );
///////////////////////////////////////////////
- rt::parameter<std::string> log_sink( LOG_SINK, (
+ rt::parameter<std::string> log_sink( btrt_log_sink, (
rt::description = "Specifies log sink: stdout(default), stderr or file name.",
rt::env_var = "BOOST_TEST_LOG_SINK",
rt::value_hint = "<stderr|stdout|file name>",
- rt::help = "Parameter " + LOG_SINK + " allows to set the log sink - location "
+ rt::help = "Parameter " + btrt_log_sink + " allows to set the log sink - location "
"where we report the log to, thus it allows to easily redirect the "
"test logs to file or standard streams. By default testing log is "
"directed to standard output."
));
- log_sink.add_cla_id( "--", LOG_SINK, "=" );
+ log_sink.add_cla_id( "--", btrt_log_sink, "=" );
log_sink.add_cla_id( "-", "k", " " );
store.add( log_sink );
///////////////////////////////////////////////
- rt::enum_parameter<unit_test::output_format> output_format( OUTPUT_FORMAT, (
+ rt::enum_parameter<unit_test::output_format> output_format( btrt_output_format, (
rt::description = "Specifies output format (both log and report).",
rt::env_var = "BOOST_TEST_OUTPUT_FORMAT",
rt::enum_values<unit_test::output_format>::value =
@@ -380,8 +380,8 @@ register_parameters( rt::parameters_store& store )
( "XML", OF_XML )
,
#endif
- rt::help = "Parameter " + OUTPUT_FORMAT + " combines an effect of " + REPORT_FORMAT +
- " and " + LOG_FORMAT + " parameters. This parameter has higher priority "
+ rt::help = "Parameter " + btrt_output_format + " combines an effect of " + btrt_report_format +
+ " and " + btrt_log_format + " parameters. This parameter has higher priority "
"than either one of them. In other words if this parameter is specified "
"it overrides the value of other two parameters. This parameter does not "
"have a default value. The only acceptable values are string names of "
@@ -389,33 +389,33 @@ register_parameters( rt::parameters_store& store )
"automation tools processing."
));
- output_format.add_cla_id( "--", OUTPUT_FORMAT, "=" );
+ output_format.add_cla_id( "--", btrt_output_format, "=" );
output_format.add_cla_id( "-", "o", " " );
store.add( output_format );
/////////////////////////////////////////////// combined logger option
- rt::parameter<std::string,rt::REPEATABLE_PARAM> combined_logger( COMBINED_LOGGER, (
+ rt::parameter<std::string,rt::REPEATABLE_PARAM> combined_logger( btrt_combined_logger, (
rt::description = "Specifies log level and sink for one or several log format",
rt::env_var = "BOOST_TEST_LOGGER",
rt::value_hint = "log_format:log_level:log_sink",
- rt::help = "Parameter " + COMBINED_LOGGER + " allows to specify the logger type, level and sink\n"
+ rt::help = "Parameter " + btrt_combined_logger + " allows to specify the logger type, level and sink\n"
"in one command."
));
- combined_logger.add_cla_id( "--", COMBINED_LOGGER, "=" );
+ combined_logger.add_cla_id( "--", btrt_combined_logger, "=" );
store.add( combined_logger );
///////////////////////////////////////////////
- rt::parameter<unsigned> random_seed( RANDOM_SEED, (
+ rt::parameter<unsigned> random_seed( btrt_random_seed, (
rt::description = "Allows to switch between sequential and random order of test units execution."
" Optionally allows to specify concrete seed for random number generator.",
rt::env_var = "BOOST_TEST_RANDOM",
rt::default_value = 0U,
rt::optional_value = 1U,
rt::value_hint = "<seed>",
- rt::help = "Parameter " + RANDOM_SEED + " instructs the framework to execute the "
+ rt::help = "Parameter " + btrt_random_seed + " instructs the framework to execute the "
"test cases in random order. This parameter accepts optional unsigned "
"integer argument. By default test cases are executed in some specific "
"order defined by order of test units in test files and dependency between "
@@ -425,12 +425,12 @@ register_parameters( rt::parameters_store& store )
"the run."
));
- random_seed.add_cla_id( "--", RANDOM_SEED, "=" );
+ random_seed.add_cla_id( "--", btrt_random_seed, "=" );
store.add( random_seed );
///////////////////////////////////////////////
- rt::enum_parameter<unit_test::output_format> report_format( REPORT_FORMAT, (
+ rt::enum_parameter<unit_test::output_format> report_format( btrt_report_format, (
rt::description = "Specifies report format.",
rt::env_var = "BOOST_TEST_REPORT_FORMAT",
rt::default_value = OF_CLF,
@@ -448,7 +448,7 @@ register_parameters( rt::parameters_store& store )
( "XML", OF_XML )
,
#endif
- rt::help = "Parameter " + REPORT_FORMAT + " allows to set the framework's report format "
+ rt::help = "Parameter " + btrt_report_format + " allows to set the framework's report format "
"to one of the formats supplied by the framework. The only acceptable values "
"for this parameter are the names of the output formats. By default the framework "
"uses human readable format (HRF) for results reporting. Alternatively you can "
@@ -456,13 +456,13 @@ register_parameters( rt::parameters_store& store )
"automation tools."
));
- report_format.add_cla_id( "--", REPORT_FORMAT, "=" );
+ report_format.add_cla_id( "--", btrt_report_format, "=" );
report_format.add_cla_id( "-", "m", " " );
store.add( report_format );
///////////////////////////////////////////////
- rt::enum_parameter<unit_test::report_level> report_level( REPORT_LEVEL, (
+ rt::enum_parameter<unit_test::report_level> report_level( btrt_report_level, (
rt::description = "Specifies report level.",
rt::env_var = "BOOST_TEST_REPORT_LEVEL",
rt::default_value = CONFIRMATION_REPORT,
@@ -482,155 +482,155 @@ register_parameters( rt::parameters_store& store )
( "no", NO_REPORT )
,
#endif
- rt::help = "Parameter " + REPORT_LEVEL + " allows to set the verbosity level of the "
+ rt::help = "Parameter " + btrt_report_level + " allows to set the verbosity level of the "
"testing result report generated by the framework. Use value 'no' to "
"eliminate the results report completely."
));
- report_level.add_cla_id( "--", REPORT_LEVEL, "=" );
+ report_level.add_cla_id( "--", btrt_report_level, "=" );
report_level.add_cla_id( "-", "r", " " );
store.add( report_level );
///////////////////////////////////////////////
- rt::parameter<std::string> report_mem_leaks( REPORT_MEM_LEAKS, (
+ rt::parameter<std::string> report_mem_leaks( btrt_report_mem_leaks, (
rt::description = "File where to report memory leaks to.",
rt::env_var = "BOOST_TEST_REPORT_MEMORY_LEAKS_TO",
rt::default_value = std::string(),
rt::value_hint = "<file name>",
- rt::help = "Parameter " + REPORT_MEM_LEAKS + " allows to specify a file where to report "
+ rt::help = "Parameter " + btrt_report_mem_leaks + " allows to specify a file where to report "
"memory leaks to. The parameter does not have default value. If it is not specified, "
"memory leaks (if any) are reported to the standard error stream."
));
- report_mem_leaks.add_cla_id( "--", REPORT_MEM_LEAKS, "=" );
+ report_mem_leaks.add_cla_id( "--", btrt_report_mem_leaks, "=" );
store.add( report_mem_leaks );
///////////////////////////////////////////////
- rt::parameter<std::string> report_sink( REPORT_SINK, (
+ rt::parameter<std::string> report_sink( btrt_report_sink, (
rt::description = "Specifies report sink: stderr(default), stdout or file name.",
rt::env_var = "BOOST_TEST_REPORT_SINK",
rt::value_hint = "<stderr|stdout|file name>",
- rt::help = "Parameter " + REPORT_SINK + " allows to set the result report sink - "
+ rt::help = "Parameter " + btrt_report_sink + " allows to set the result report sink - "
"the location where the framework writes the result report to, thus it "
"allows to easily redirect the result report to a file or a standard "
"stream. By default the testing result report is directed to the "
"standard error stream."
));
- report_sink.add_cla_id( "--", REPORT_SINK, "=" );
+ report_sink.add_cla_id( "--", btrt_report_sink, "=" );
report_sink.add_cla_id( "-", "e", " " );
store.add( report_sink );
///////////////////////////////////////////////
- rt::option result_code( RESULT_CODE, (
+ rt::option result_code( btrt_result_code, (
rt::description = "Disables test modules's result code generation.",
rt::env_var = "BOOST_TEST_RESULT_CODE",
rt::default_value = true,
- rt::help = "The 'no' argument value for the parameter " + RESULT_CODE + " instructs the "
+ rt::help = "The 'no' argument value for the parameter " + btrt_result_code + " instructs the "
"framework to always return zero result code. This can be used for test programs "
"executed within IDE. By default this parameter has value 'yes'."
));
- result_code.add_cla_id( "--", RESULT_CODE, "=", true );
+ result_code.add_cla_id( "--", btrt_result_code, "=", true );
result_code.add_cla_id( "-", "c", " " );
store.add( result_code );
///////////////////////////////////////////////
- rt::parameter<std::string,rt::REPEATABLE_PARAM> tests_to_run( RUN_FILTERS, (
+ rt::parameter<std::string,rt::REPEATABLE_PARAM> tests_to_run( btrt_run_filters, (
rt::description = "Filters, which test units to include or exclude from test module execution.",
rt::env_var = "BOOST_TEST_RUN_FILTERS",
rt::value_hint = "<test unit filter>",
- rt::help = "Parameter " + RUN_FILTERS + " allows to filter which test units to execute during "
+ rt::help = "Parameter " + btrt_run_filters + " allows to filter which test units to execute during "
"testing. The framework supports both 'selection filters', which allow to select "
"which test units to enable from the set of available test units, and 'disabler "
"filters', which allow to disable some test units. The __UTF__ also supports "
"enabling/disabling test units at compile time. These settings identify the default "
- "set of test units to run. Parameter " + RUN_FILTERS + " is used to change this default. "
+ "set of test units to run. Parameter " + btrt_run_filters + " is used to change this default. "
"This parameter is repeatable, so you can specify more than one filter if necessary."
));
- tests_to_run.add_cla_id( "--", RUN_FILTERS, "=" );
+ tests_to_run.add_cla_id( "--", btrt_run_filters, "=" );
tests_to_run.add_cla_id( "-", "t", " " );
store.add( tests_to_run );
///////////////////////////////////////////////
- rt::option save_test_pattern( SAVE_TEST_PATTERN, (
+ rt::option save_test_pattern( btrt_save_test_pattern, (
rt::description = "Allows to switch between saving or matching test pattern file.",
rt::env_var = "BOOST_TEST_SAVE_PATTERN",
- rt::help = "Parameter " + SAVE_TEST_PATTERN + " facilitates switching mode of operation for "
+ rt::help = "Parameter " + btrt_save_test_pattern + " facilitates switching mode of operation for "
"testing output streams.\n\nThis parameter serves no particular purpose within the "
"framework itself. It can be used by test modules relying on output_test_stream to "
"implement testing logic. Default mode is 'match' (false)."
));
- save_test_pattern.add_cla_id( "--", SAVE_TEST_PATTERN, "=" );
+ save_test_pattern.add_cla_id( "--", btrt_save_test_pattern, "=" );
store.add( save_test_pattern );
///////////////////////////////////////////////
- rt::option show_progress( SHOW_PROGRESS, (
+ rt::option show_progress( btrt_show_progress, (
rt::description = "Turns on progress display.",
rt::env_var = "BOOST_TEST_SHOW_PROGRESS",
- rt::help = "Parameter " + SHOW_PROGRESS + " instructs the framework to display test progress "
+ rt::help = "Parameter " + btrt_show_progress + " instructs the framework to display test progress "
"information. By default the test progress is not shown."
));
- show_progress.add_cla_id( "--", SHOW_PROGRESS, "=" );
+ show_progress.add_cla_id( "--", btrt_show_progress, "=" );
show_progress.add_cla_id( "-", "p", " " );
store.add( show_progress );
///////////////////////////////////////////////
- rt::option use_alt_stack( USE_ALT_STACK, (
+ rt::option use_alt_stack( btrt_use_alt_stack, (
rt::description = "Turns on/off usage of an alternative stack for signal handling.",
rt::env_var = "BOOST_TEST_USE_ALT_STACK",
rt::default_value = true,
- rt::help = "Parameter " + USE_ALT_STACK + " instructs the framework to use alternative "
+ rt::help = "Parameter " + btrt_use_alt_stack + " instructs the framework to use alternative "
"stack for signals processing, on platforms where they are supported. The feature "
"is enabled by default, but can be disabled using this parameter."
));
- use_alt_stack.add_cla_id( "--", USE_ALT_STACK, "=", true );
+ use_alt_stack.add_cla_id( "--", btrt_use_alt_stack, "=", true );
store.add( use_alt_stack );
///////////////////////////////////////////////
- rt::option wait_for_debugger( WAIT_FOR_DEBUGGER, (
+ rt::option wait_for_debugger( btrt_wait_for_debugger, (
rt::description = "Forces test module to wait for button to be pressed before starting test run.",
rt::env_var = "BOOST_TEST_WAIT_FOR_DEBUGGER",
- rt::help = "Parameter " + WAIT_FOR_DEBUGGER + " instructs the framework to pause before starting "
+ rt::help = "Parameter " + btrt_wait_for_debugger + " instructs the framework to pause before starting "
"test units execution, so that you can attach a debugger to running test module. By "
"default this parameters turned off."
));
- wait_for_debugger.add_cla_id( "--", WAIT_FOR_DEBUGGER, "=" );
+ wait_for_debugger.add_cla_id( "--", btrt_wait_for_debugger, "=" );
wait_for_debugger.add_cla_id( "-", "w", " " );
store.add( wait_for_debugger );
///////////////////////////////////////////////
- rt::parameter<std::string> help( HELP, (
+ rt::parameter<std::string> help( btrt_help, (
rt::description = "Help for framework parameters.",
rt::optional_value = std::string(),
rt::value_hint = "<parameter name>",
- rt::help = "Parameter " + HELP + " displays help on the framework's parameters. "
+ rt::help = "Parameter " + btrt_help + " displays help on the framework's parameters. "
"The parameter accepts an optional argument value. If present, an argument value is "
"interpreted as a parameter name (name guessing works as well, so for example "
"--help=rand displays help on the parameter random). If the parameter name is unknown "
"or ambiguous error is reported. If argument value is absent, a summary of all "
"framework's parameter is displayed."
));
- help.add_cla_id( "--", HELP, "=" );
+ help.add_cla_id( "--", btrt_help, "=" );
store.add( help );
///////////////////////////////////////////////
- rt::option usage( USAGE, (
+ rt::option usage( btrt_usage, (
rt::description = "Short message explaining usage of Boost.Test parameters."
));
usage.add_cla_id( "-", "?", " " );
@@ -638,10 +638,10 @@ register_parameters( rt::parameters_store& store )
///////////////////////////////////////////////
- rt::option version( VERSION, (
+ rt::option version( btrt_version, (
rt::description = "Prints Boost.Test version and exits."
));
- version.add_cla_id( "--", VERSION, " " );
+ version.add_cla_id( "--", btrt_version, " " );
store.add( version );
}
@@ -676,24 +676,24 @@ init( int& argc, char** argv )
rt::finalize_arguments( s_parameters_store, s_arguments_store );
// Report help if requested
- if( runtime_config::get<bool>( VERSION ) ) {
+ if( runtime_config::get<bool>( btrt_version ) ) {
parser->version( std::cerr );
BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_success ) );
}
- else if( runtime_config::get<bool>( USAGE ) ) {
+ else if( runtime_config::get<bool>( btrt_usage ) ) {
parser->usage( std::cerr );
BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_success ) );
}
- else if( s_arguments_store.has( HELP ) ) {
- parser->help( std::cerr, s_parameters_store, runtime_config::get<std::string>( HELP ) );
+ else if( s_arguments_store.has( btrt_help ) ) {
+ parser->help( std::cerr, s_parameters_store, runtime_config::get<std::string>( btrt_help ) );
BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_success ) );
}
// A bit of business logic: output_format takes precedence over log/report formats
- if( s_arguments_store.has( OUTPUT_FORMAT ) ) {
- unit_test::output_format of = s_arguments_store.get<unit_test::output_format>( OUTPUT_FORMAT );
- s_arguments_store.set( REPORT_FORMAT, of );
- s_arguments_store.set( LOG_FORMAT, of );
+ if( s_arguments_store.has( btrt_output_format ) ) {
+ unit_test::output_format of = s_arguments_store.get<unit_test::output_format>( btrt_output_format );
+ s_arguments_store.set( btrt_report_format, of );
+ s_arguments_store.set( btrt_log_format, of );
}
}
@@ -747,7 +747,7 @@ argument_store()
bool
save_pattern()
{
- return runtime_config::get<bool>( SAVE_TEST_PATTERN );
+ return runtime_config::get<bool>( btrt_save_test_pattern );
}
//____________________________________________________________________________//
diff --git a/boost/test/output/junit_log_formatter.hpp b/boost/test/output/junit_log_formatter.hpp
index b6e818e37f..325a1d8a17 100644
--- a/boost/test/output/junit_log_formatter.hpp
+++ b/boost/test/output/junit_log_formatter.hpp
@@ -49,7 +49,7 @@ namespace output {
assertion_entry() : sealed(false)
{}
- std::string logentry_message;
+ std::string logentry_message; // the message associated to the JUnit error/entry
std::string logentry_type; // the one that will get expanded in the final junit (failure, error)
std::string output; // additional information/message generated by the assertion
@@ -58,12 +58,26 @@ namespace output {
bool sealed; // indicates if the entry can accept additional information
};
- std::string system_out; // sysout: additional information
- std::string system_err; // syserr: additional information
+ std::list<std::string> system_out; // sysout: additional information
+ std::list<std::string> system_err; // syserr: additional information
+ std::string skipping_reason;
// list of failure, errors and messages (assertions message and the full log)
std::vector< assertion_entry > assertion_entries;
+ bool skipping;
+
+ junit_log_helper(): skipping(false)
+ {}
+
+ void clear() {
+ assertion_entries.clear();
+ system_out.clear();
+ system_err.clear();
+ skipping_reason.clear();
+ skipping = false;
+ }
+
};
}
@@ -77,7 +91,11 @@ public:
junit_log_formatter() : m_display_build_info(false)
{
- this->m_log_level = log_successful_tests;
+ // we log everything from the logger singleton point of view
+ // because we need to know about all the messages/commands going to the logger
+ // we decide what we put inside the logs internally
+ this->m_log_level = log_successful_tests;
+ m_log_level_internal = log_messages;
}
// Formatter interface
@@ -104,8 +122,14 @@ public:
void entry_context_finish( std::ostream& );
//! Discards changes in the log level
- virtual void set_log_level(log_level )
+ virtual void set_log_level(log_level ll)
{
+ if(ll > log_successful_tests && ll < log_messages)
+ ll = log_successful_tests;
+ else if (ll > log_all_errors)
+ ll = log_all_errors;
+
+ this->m_log_level_internal = ll;
}
//! Instead of a regular stream, returns a file name corresponding to
@@ -117,12 +141,20 @@ public:
private:
typedef std::map<test_unit_id, junit_impl::junit_log_helper> map_trace_t;
map_trace_t map_tests;
+ junit_impl::junit_log_helper runner_log_entry;
+
+ junit_impl::junit_log_helper& get_current_log_entry() {
+ if(list_path_to_root.empty())
+ return runner_log_entry;
+ map_trace_t::iterator it = map_tests.find(list_path_to_root.back());
+ return (it == map_tests.end() ? runner_log_entry : it->second);
+ }
std::list<test_unit_id> list_path_to_root;
- test_unit_id root_id;
bool m_display_build_info;
bool m_is_last_assertion_or_error; // true if failure, false if error
+ log_level m_log_level_internal;
friend class junit_result_helper;
};
diff --git a/boost/test/tools/detail/print_helper.hpp b/boost/test/tools/detail/print_helper.hpp
index 39ab707f36..1e4dd6e3c0 100644
--- a/boost/test/tools/detail/print_helper.hpp
+++ b/boost/test/tools/detail/print_helper.hpp
@@ -30,6 +30,10 @@
#include <limits>
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+#include <cstddef>
+#endif
+
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
@@ -39,21 +43,51 @@ namespace test_tools {
namespace tt_detail {
// ************************************************************************** //
+// ************** boost_test_print_type ************** //
+// ************************************************************************** //
+
+ namespace impl {
+ template <class T>
+ std::ostream& boost_test_print_type(std::ostream& ostr, T const& t) {
+ BOOST_STATIC_ASSERT_MSG( (boost::has_left_shift<std::ostream,T>::value),
+ "Type has to implement operator<< to be printable");
+ ostr << t;
+ return ostr;
+ }
+
+ struct boost_test_print_type_impl {
+ template <class R>
+ std::ostream& operator()(std::ostream& ostr, R const& r) const {
+ return boost_test_print_type(ostr, r);
+ }
+ };
+ }
+
+ // To avoid ODR violations, see N4381
+ template <class T> struct static_const { static const T value; };
+ template <class T> const T static_const<T>::value = T();
+
+ namespace {
+ static const impl::boost_test_print_type_impl& boost_test_print_type =
+ static_const<impl::boost_test_print_type_impl>::value;
+ }
+
+
+// ************************************************************************** //
// ************** print_log_value ************** //
// ************************************************************************** //
template<typename T>
struct print_log_value {
- BOOST_STATIC_ASSERT_MSG( (boost::has_left_shift<std::ostream,T>::value),
- "Type has to implement operator<< to be printable");
-
void operator()( std::ostream& ostr, T const& t )
{
typedef typename mpl::or_<is_array<T>,is_function<T>,is_abstract<T> >::type cant_use_nl;
std::streamsize old_precision = set_precision( ostr, cant_use_nl() );
- ostr << t;
+ //ostr << t;
+ using boost::test_tools::tt_detail::boost_test_print_type;
+ boost_test_print_type(ostr, t);
if( old_precision != (std::streamsize)-1 )
ostr.precision( old_precision );
@@ -99,10 +133,7 @@ struct print_log_value< T[N] > {
template<>
struct BOOST_TEST_DECL print_log_value<bool> {
- void operator()( std::ostream& ostr, bool t )
- {
- ostr << std::boolalpha << t;
- }
+ void operator()( std::ostream& ostr, bool t );
};
//____________________________________________________________________________//
@@ -133,6 +164,13 @@ struct BOOST_TEST_DECL print_log_value<wchar_t const*> {
void operator()( std::ostream& ostr, wchar_t const* t );
};
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+template<>
+struct BOOST_TEST_DECL print_log_value<std::nullptr_t> {
+ void operator()( std::ostream& ostr, std::nullptr_t t );
+};
+#endif
+
//____________________________________________________________________________//
// ************************************************************************** //
diff --git a/boost/test/unit_test_parameters.hpp b/boost/test/unit_test_parameters.hpp
index 4ac4eaee1f..0b77f37197 100644
--- a/boost/test/unit_test_parameters.hpp
+++ b/boost/test/unit_test_parameters.hpp
@@ -36,31 +36,34 @@ namespace runtime_config {
// ************************************************************************** //
// UTF parameters
-BOOST_TEST_DECL extern std::string AUTO_START_DBG;
-BOOST_TEST_DECL extern std::string BREAK_EXEC_PATH;
-BOOST_TEST_DECL extern std::string BUILD_INFO;
-BOOST_TEST_DECL extern std::string CATCH_SYS_ERRORS;
-BOOST_TEST_DECL extern std::string COLOR_OUTPUT;
-BOOST_TEST_DECL extern std::string DETECT_FP_EXCEPT;
-BOOST_TEST_DECL extern std::string DETECT_MEM_LEAKS;
-BOOST_TEST_DECL extern std::string LIST_CONTENT;
-BOOST_TEST_DECL extern std::string LIST_LABELS;
-BOOST_TEST_DECL extern std::string COMBINED_LOGGER;
-BOOST_TEST_DECL extern std::string LOG_FORMAT;
-BOOST_TEST_DECL extern std::string LOG_LEVEL;
-BOOST_TEST_DECL extern std::string LOG_SINK;
-BOOST_TEST_DECL extern std::string OUTPUT_FORMAT;
-BOOST_TEST_DECL extern std::string RANDOM_SEED;
-BOOST_TEST_DECL extern std::string REPORT_FORMAT;
-BOOST_TEST_DECL extern std::string REPORT_LEVEL;
-BOOST_TEST_DECL extern std::string REPORT_MEM_LEAKS;
-BOOST_TEST_DECL extern std::string REPORT_SINK;
-BOOST_TEST_DECL extern std::string RESULT_CODE;
-BOOST_TEST_DECL extern std::string RUN_FILTERS;
-BOOST_TEST_DECL extern std::string SAVE_TEST_PATTERN;
-BOOST_TEST_DECL extern std::string SHOW_PROGRESS;
-BOOST_TEST_DECL extern std::string USE_ALT_STACK;
-BOOST_TEST_DECL extern std::string WAIT_FOR_DEBUGGER;
+BOOST_TEST_DECL extern std::string btrt_auto_start_dbg;
+BOOST_TEST_DECL extern std::string btrt_break_exec_path;
+BOOST_TEST_DECL extern std::string btrt_build_info;
+BOOST_TEST_DECL extern std::string btrt_catch_sys_errors;
+BOOST_TEST_DECL extern std::string btrt_color_output;
+BOOST_TEST_DECL extern std::string btrt_detect_fp_except;
+BOOST_TEST_DECL extern std::string btrt_detect_mem_leaks;
+BOOST_TEST_DECL extern std::string btrt_list_content;
+BOOST_TEST_DECL extern std::string btrt_list_labels;
+BOOST_TEST_DECL extern std::string btrt_log_format;
+BOOST_TEST_DECL extern std::string btrt_log_level;
+BOOST_TEST_DECL extern std::string btrt_log_sink;
+BOOST_TEST_DECL extern std::string btrt_combined_logger;
+BOOST_TEST_DECL extern std::string btrt_output_format;
+BOOST_TEST_DECL extern std::string btrt_random_seed;
+BOOST_TEST_DECL extern std::string btrt_report_format;
+BOOST_TEST_DECL extern std::string btrt_report_level;
+BOOST_TEST_DECL extern std::string btrt_report_mem_leaks;
+BOOST_TEST_DECL extern std::string btrt_report_sink;
+BOOST_TEST_DECL extern std::string btrt_result_code;
+BOOST_TEST_DECL extern std::string btrt_run_filters;
+BOOST_TEST_DECL extern std::string btrt_save_test_pattern;
+BOOST_TEST_DECL extern std::string btrt_show_progress;
+BOOST_TEST_DECL extern std::string btrt_use_alt_stack;
+BOOST_TEST_DECL extern std::string btrt_wait_for_debugger;
+BOOST_TEST_DECL extern std::string btrt_help;
+BOOST_TEST_DECL extern std::string btrt_usage;
+BOOST_TEST_DECL extern std::string btrt_version;
BOOST_TEST_DECL void init( int& argc, char** argv );
diff --git a/boost/test/unit_test_suite.hpp b/boost/test/unit_test_suite.hpp
index 1dbcece78a..b434fa9f97 100644
--- a/boost/test/unit_test_suite.hpp
+++ b/boost/test/unit_test_suite.hpp
@@ -120,9 +120,9 @@ typedef F BOOST_AUTO_TEST_CASE_FIXTURE; \
// ************** BOOST_AUTO_TEST_SUITE_END ************** //
// ************************************************************************** //
-#define BOOST_AUTO_TEST_SUITE_END() \
-BOOST_AUTO_TU_REGISTRAR( BOOST_JOIN( end_suite, __LINE__ ) )( 1 ); \
-} \
+#define BOOST_AUTO_TEST_SUITE_END() \
+BOOST_AUTO_TU_REGISTRAR( end_suite )( 1 ); \
+} \
/**/
// ************************************************************************** //
@@ -299,7 +299,7 @@ static boost::unit_test::ut_detail::global_fixture_impl<F> BOOST_JOIN( gf_, F )
#define BOOST_TEST_DECORATOR( D ) \
static boost::unit_test::decorator::collector const& \
-BOOST_JOIN(decorator_collector,__LINE__) = D; \
+BOOST_TEST_APPEND_UNIQUE_ID(decorator_collector) = D; \
/**/
// ************************************************************************** //
@@ -321,9 +321,25 @@ typedef ::boost::unit_test::ut_detail::nil_t BOOST_AUTO_TEST_CASE_FIXTURE;
// ************** Auto registration facility helper macros ************** //
// ************************************************************************** //
-#define BOOST_AUTO_TU_REGISTRAR( test_name ) \
-static boost::unit_test::ut_detail::auto_test_unit_registrar \
-BOOST_JOIN( BOOST_JOIN( test_name, _registrar ), __LINE__ ) \
+// Facility for having a unique name based on __LINE__ and __COUNTER__ (later if available)
+#if defined(__COUNTER__)
+ #define BOOST_TEST_INTERNAL_HAS_COUNTER
+#endif
+
+#if defined(BOOST_TEST_INTERNAL_HAS_COUNTER)
+ #define BOOST_TEST_APPEND_UNIQUE_ID( name ) \
+ BOOST_JOIN( BOOST_JOIN( name, __LINE__ ), __COUNTER__)
+ /**/
+#else
+ #define BOOST_TEST_APPEND_UNIQUE_ID( name ) \
+ BOOST_JOIN( name, __LINE__ )
+ /**/
+#endif
+/**/
+
+#define BOOST_AUTO_TU_REGISTRAR( test_name ) \
+static boost::unit_test::ut_detail::auto_test_unit_registrar \
+BOOST_TEST_APPEND_UNIQUE_ID( BOOST_JOIN( test_name, _registrar ) ) \
/**/
#define BOOST_AUTO_TC_INVOKER( test_name ) BOOST_JOIN( test_name, _invoker )
#define BOOST_AUTO_TC_UNIQUE_ID( test_name ) BOOST_JOIN( test_name, _id )
diff --git a/boost/thread/detail/config.hpp b/boost/thread/detail/config.hpp
index b060b81c95..6d1595ebc7 100644
--- a/boost/thread/detail/config.hpp
+++ b/boost/thread/detail/config.hpp
@@ -12,6 +12,8 @@
#include <boost/detail/workaround.hpp>
#include <boost/thread/detail/platform.hpp>
+//#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 9e7e8b8f5e..bd2f149a0e 100644
--- a/boost/thread/detail/thread.hpp
+++ b/boost/thread/detail/thread.hpp
@@ -482,13 +482,20 @@ namespace boost
return try_join_until(chrono::steady_clock::now() + rel_time);
}
#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 {
- system_clock::time_point s_now = system_clock::now();
+ my_clock_t::time_point s_now = my_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);
@@ -496,10 +503,10 @@ namespace boost
return true;
}
template <class Duration>
- bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t)
+ bool try_join_until(const chrono::time_point<my_clock_t, Duration>& t)
{
using namespace chrono;
- typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
+ typedef time_point<my_clock_t, nanoseconds> nano_sys_tmpt;
return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
#endif
@@ -514,7 +521,7 @@ namespace boost
//}
#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<my_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());
diff --git a/boost/thread/exceptions.hpp b/boost/thread/exceptions.hpp
index d97465b754..a3934f0799 100644
--- a/boost/thread/exceptions.hpp
+++ b/boost/thread/exceptions.hpp
@@ -40,19 +40,19 @@ namespace boost
typedef system::system_error base_type;
public:
thread_exception()
- : base_type(0,system::system_category())
+ : base_type(0,system::generic_category())
{}
thread_exception(int sys_error_code)
- : base_type(sys_error_code, system::system_category())
+ : base_type(sys_error_code, system::generic_category())
{}
thread_exception( int ev, const char * what_arg )
- : base_type(system::error_code(ev, system::system_category()), what_arg)
+ : base_type(system::error_code(ev, system::generic_category()), what_arg)
{
}
thread_exception( int ev, const std::string & what_arg )
- : base_type(system::error_code(ev, system::system_category()), what_arg)
+ : base_type(system::error_code(ev, system::generic_category()), what_arg)
{
}
@@ -74,18 +74,18 @@ namespace boost
typedef system::system_error base_type;
public:
condition_error()
- : base_type(system::error_code(0, system::system_category()), "Condition error")
+ : base_type(system::error_code(0, system::generic_category()), "Condition error")
{}
condition_error( int ev )
- : base_type(system::error_code(ev, system::system_category()), "Condition error")
+ : base_type(system::error_code(ev, system::generic_category()), "Condition error")
{
}
condition_error( int ev, const char * what_arg )
- : base_type(system::error_code(ev, system::system_category()), what_arg)
+ : base_type(system::error_code(ev, system::generic_category()), what_arg)
{
}
condition_error( int ev, const std::string & what_arg )
- : base_type(system::error_code(ev, system::system_category()), what_arg)
+ : base_type(system::error_code(ev, system::generic_category()), what_arg)
{
}
};
diff --git a/boost/thread/executors/executor.hpp b/boost/thread/executors/executor.hpp
index 96198201f0..1c751dd094 100644
--- a/boost/thread/executors/executor.hpp
+++ b/boost/thread/executors/executor.hpp
@@ -38,7 +38,7 @@ namespace boost
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
- virtual ~executor() {};
+ virtual ~executor() {}
/**
* \par Effects
diff --git a/boost/thread/executors/generic_executor_ref.hpp b/boost/thread/executors/generic_executor_ref.hpp
index da0382c160..1353dd3277 100644
--- a/boost/thread/executors/generic_executor_ref.hpp
+++ b/boost/thread/executors/generic_executor_ref.hpp
@@ -41,7 +41,7 @@ namespace boost
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
- ~executor_ref() {};
+ ~executor_ref() {}
/**
* \par Effects
diff --git a/boost/thread/executors/loop_executor.hpp b/boost/thread/executors/loop_executor.hpp
index b08ff76f57..aee7a8d477 100644
--- a/boost/thread/executors/loop_executor.hpp
+++ b/boost/thread/executors/loop_executor.hpp
@@ -16,6 +16,7 @@
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
+#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -41,14 +42,32 @@ namespace executors
*/
bool try_executing_one()
{
+ return execute_one(/*wait:*/false);
+ }
+
+ private:
+ /**
+ * Effects: Execute one task.
+ * Remark: If wait is true, waits until a task is available or the executor
+ * is closed. If wait is false, returns false immediately if no
+ * task is available.
+ * Returns: whether a task has been executed (if wait is true, only returns false if closed).
+ * Throws: whatever the current task constructor throws or the task() throws.
+ */
+ bool execute_one(bool wait)
+ {
work task;
try
{
- if (work_queue.try_pull(task) == queue_op_status::success)
+ queue_op_status status = wait ?
+ work_queue.wait_pull(task) :
+ work_queue.try_pull(task);
+ if (status == queue_op_status::success)
{
task();
return true;
}
+ BOOST_ASSERT(!wait || status == queue_op_status::closed);
return false;
}
catch (...)
@@ -57,21 +76,6 @@ namespace executors
//return false;
}
}
- private:
- /**
- * Effects: schedule one task or yields
- * Throws: whatever the current task constructor throws or the task() throws.
- */
- void schedule_one_or_yield()
- {
- if ( ! try_executing_one())
- {
- this_thread::yield();
- }
- }
-
-
-
public:
/// loop_executor is not copyable.
@@ -101,10 +105,10 @@ namespace executors
*/
void loop()
{
- while (!closed())
+ while (execute_one(/*wait:*/true))
{
- schedule_one_or_yield();
}
+ BOOST_ASSERT(closed());
while (try_executing_one())
{
}
diff --git a/boost/thread/future.hpp b/boost/thread/future.hpp
index b98ff3d338..59712c7e2f 100644
--- a/boost/thread/future.hpp
+++ b/boost/thread/future.hpp
@@ -1355,7 +1355,7 @@ namespace boost
boost::throw_exception(future_uninitialized());
}
return future_->mutex;
- };
+ }
notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv)
{
@@ -5656,5 +5656,5 @@ namespace detail
#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
}
-#endif // BOOST_NO_EXCEPTION
+#endif // BOOST_NO_EXCEPTIONS
#endif // header
diff --git a/boost/thread/futures/wait_for_all.hpp b/boost/thread/futures/wait_for_all.hpp
index 90cc2b77cb..398eb4adee 100644
--- a/boost/thread/futures/wait_for_all.hpp
+++ b/boost/thread/futures/wait_for_all.hpp
@@ -60,7 +60,7 @@ namespace boost
}
#else
template<typename F1, typename... Fs>
- void wait_for_all(F1& f1, Fs&... fs)
+ typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1, Fs&... fs)
{
bool dummy[] = { (f1.wait(), true), (fs.wait(), true)... };
diff --git a/boost/thread/pthread/condition_variable_fwd.hpp b/boost/thread/pthread/condition_variable_fwd.hpp
index 652a8c0baa..802a5cc674 100644
--- a/boost/thread/pthread/condition_variable_fwd.hpp
+++ b/boost/thread/pthread/condition_variable_fwd.hpp
@@ -17,6 +17,7 @@
#if defined BOOST_THREAD_USES_DATETIME
#include <boost/thread/xtime.hpp>
#endif
+
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
@@ -68,7 +69,20 @@ namespace boost
unique_lock<mutex>& lock,
struct timespec const &timeout)
{
- return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now()));
+#if ! defined BOOST_THREAD_USEFIXES_TIMESPEC
+ return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now()));
+#elif ! defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+ //using namespace chrono;
+ //nanoseconds ns = chrono::system_clock::now().time_since_epoch();
+
+ struct timespec ts = boost::detail::timespec_now_realtime();
+ //ts.tv_sec = static_cast<long>(chrono::duration_cast<chrono::seconds>(ns).count());
+ //ts.tv_nsec = static_cast<long>((ns - chrono::duration_cast<chrono::seconds>(ns)).count());
+ return do_wait_until(lock, boost::detail::timespec_plus(timeout, ts));
+#else
+ // old behavior was fine for monotonic
+ return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_realtime()));
+#endif
}
public:
diff --git a/boost/thread/pthread/timespec.hpp b/boost/thread/pthread/timespec.hpp
index 82f50f6ca7..74583ed0eb 100644
--- a/boost/thread/pthread/timespec.hpp
+++ b/boost/thread/pthread/timespec.hpp
@@ -75,6 +75,33 @@ namespace boost
{
timespec ts;
+#if defined CLOCK_MONOTONIC && defined BOOST_THREAD_USEFIXES_TIMESPEC
+ if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
+ {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
+ }
+#elif defined(BOOST_THREAD_TIMESPEC_MAC_API)
+ timeval tv;
+ ::gettimeofday(&tv, 0);
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+#else
+ if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
+ {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
+ }
+#endif
+ return ts;
+ }
+
+ inline timespec timespec_now_realtime()
+ {
+ timespec ts;
+
#if defined(BOOST_THREAD_TIMESPEC_MAC_API)
timeval tv;
::gettimeofday(&tv, 0);
@@ -83,6 +110,8 @@ namespace boost
#else
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
{
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
}
#endif
diff --git a/boost/thread/scoped_thread.hpp b/boost/thread/scoped_thread.hpp
index c2da919728..6cda931a5f 100644
--- a/boost/thread/scoped_thread.hpp
+++ b/boost/thread/scoped_thread.hpp
@@ -34,10 +34,10 @@ namespace boost
* boost::strict_scoped_thread<> t((boost::thread(F)));
*
*/
- template <class CallableThread = join_if_joinable>
+ template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
class strict_scoped_thread
{
- thread t_;
+ Thread t_;
struct dummy;
public:
@@ -47,13 +47,13 @@ namespace boost
*
*/
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, thread>, void* >::type>
+ template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type>
explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
#else
template <class F>
explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f,
- typename disable_if<is_same<typename decay<F>::type, thread>, void* >::type=0) :
+ typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type=0) :
t_(boost::forward<F>(f)) {}
template <class F, class A1>
strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) :
@@ -73,7 +73,7 @@ namespace boost
*
* Effects: move the thread to own @c t.
*/
- explicit strict_scoped_thread(BOOST_THREAD_RV_REF(thread) t) BOOST_NOEXCEPT :
+ explicit strict_scoped_thread(BOOST_THREAD_RV_REF(Thread) t) BOOST_NOEXCEPT :
t_(boost::move(t))
{
}
@@ -111,14 +111,15 @@ namespace boost
* t.interrupt();
*
*/
- template <class CallableThread = join_if_joinable>
+ template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
class scoped_thread
{
- thread t_;
+ Thread t_;
struct dummy;
public:
- typedef thread::id id;
+ typedef typename Thread::id id;
+ typedef typename Thread::native_handle_type native_handle_type;
BOOST_THREAD_MOVABLE_ONLY( scoped_thread) /// Movable only
@@ -137,13 +138,13 @@ namespace boost
*/
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, thread>, void* >::type>
+ template <class F, class ...Args, typename = typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type>
explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) :
t_(boost::forward<F>(f), boost::forward<Args>(args)...) {}
#else
template <class F>
explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f,
- typename disable_if<is_same<typename decay<F>::type, thread>, void* >::type=0) :
+ typename disable_if<is_same<typename decay<F>::type, Thread>, void* >::type=0) :
t_(boost::forward<F>(f)) {}
template <class F, class A1>
scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) :
@@ -163,12 +164,12 @@ namespace boost
*
* Effects: move the thread to own @c t.
*/
- explicit scoped_thread(BOOST_THREAD_RV_REF(thread) t) BOOST_NOEXCEPT :
+ explicit scoped_thread(BOOST_THREAD_RV_REF(Thread) t) BOOST_NOEXCEPT :
t_(boost::move(t))
{
}
-// explicit operator thread()
+// explicit operator Thread()
// {
// return boost::move(t_);
// }
@@ -213,7 +214,7 @@ namespace boost
}
// forwarded thread functions
- inline thread::id get_id() const BOOST_NOEXCEPT
+ inline id get_id() const BOOST_NOEXCEPT
{
return t_.get_id();
}
@@ -242,7 +243,7 @@ namespace boost
}
#endif
- thread::native_handle_type native_handle()BOOST_NOEXCEPT
+ native_handle_type native_handle()BOOST_NOEXCEPT
{
return t_.native_handle();
}
@@ -266,13 +267,13 @@ namespace boost
static unsigned hardware_concurrency() BOOST_NOEXCEPT
{
- return thread::hardware_concurrency();
+ return Thread::hardware_concurrency();
}
#ifdef BOOST_THREAD_PROVIDES_PHYSICAL_CONCURRENCY
static unsigned physical_concurrency() BOOST_NOEXCEPT
{
- return thread::physical_concurrency();
+ return Thread::physical_concurrency();
}
#endif
};
@@ -280,12 +281,13 @@ namespace boost
/**
* Effects: swaps the contents of two scoped threads.
*/
- template <class Destroyer>
- void swap(scoped_thread<Destroyer>& lhs, scoped_thread<Destroyer>& rhs)
+ template <class Destroyer, class Thread >
+ void swap(scoped_thread<Destroyer, Thread>& lhs, scoped_thread<Destroyer, Thread>& rhs)
BOOST_NOEXCEPT {
return lhs.swap(rhs);
}
+ typedef scoped_thread<> joining_thread;
}
#include <boost/config/abi_suffix.hpp>
diff --git a/boost/thread/thread_functors.hpp b/boost/thread/thread_functors.hpp
index bba129f767..f134593ffe 100644
--- a/boost/thread/thread_functors.hpp
+++ b/boost/thread/thread_functors.hpp
@@ -21,15 +21,29 @@ namespace boost
struct detach
{
- void operator()(thread& t)
+ template <class Thread>
+ void operator()(Thread& t)
{
t.detach();
}
};
+ struct detach_if_joinable
+ {
+ template <class Thread>
+ void operator()(Thread& t)
+ {
+ if (t.joinable())
+ {
+ t.detach();
+ }
+ }
+ };
+
struct join_if_joinable
{
- void operator()(thread& t)
+ template <class Thread>
+ void operator()(Thread& t)
{
if (t.joinable())
{
@@ -41,7 +55,8 @@ namespace boost
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
struct interrupt_and_join_if_joinable
{
- void operator()(thread& t)
+ template <class Thread>
+ void operator()(Thread& t)
{
if (t.joinable())
{
diff --git a/boost/thread/thread_guard.hpp b/boost/thread/thread_guard.hpp
index 85157f101e..64eb453c73 100644
--- a/boost/thread/thread_guard.hpp
+++ b/boost/thread/thread_guard.hpp
@@ -21,14 +21,14 @@ namespace boost
/**
* Non-copyable RAII scoped thread guard joiner which join the thread if joinable when destroyed.
*/
- template <class CallableThread = join_if_joinable>
+ template <class CallableThread = join_if_joinable, class Thread=::boost::thread>
class thread_guard
{
- thread& t_;
+ Thread& t_;
public:
BOOST_THREAD_NO_COPYABLE( thread_guard)
- explicit thread_guard(thread& t) :
+ explicit thread_guard(Thread& t) :
t_(t)
{
}
diff --git a/boost/thread/win32/interlocked_read.hpp b/boost/thread/win32/interlocked_read.hpp
index 2ad3fe9017..775555e184 100644
--- a/boost/thread/win32/interlocked_read.hpp
+++ b/boost/thread/win32/interlocked_read.hpp
@@ -5,6 +5,7 @@
//
// (C) Copyright 2005-8 Anthony Williams
// (C) Copyright 2012 Vicente J. Botet Escriba
+// (C) Copyright 2017 Andrey Semashev
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -15,36 +16,172 @@
#include <boost/config/abi_prefix.hpp>
-#ifdef BOOST_MSVC
+// Define compiler barriers
+#if defined(__INTEL_COMPILER)
+#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() __memory_barrier()
+#elif defined(_MSC_VER) && !defined(_WIN32_WCE)
+extern "C" void _ReadWriteBarrier(void);
+#pragma intrinsic(_ReadWriteBarrier)
+#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() _ReadWriteBarrier()
+#endif
+
+#ifndef BOOST_THREAD_DETAIL_COMPILER_BARRIER
+#define BOOST_THREAD_DETAIL_COMPILER_BARRIER()
+#endif
+
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+
+// Since VS2005 and until VS2012 volatile reads always acquire and volatile writes are always release.
+// But VS2012 adds a compiler switch that can change behavior to the standard. On x86 though
+// the compiler generates a single instruction for the load/store, which is enough synchronization
+// as far as uarch is concerned. To prevent compiler reordering code around the load/store we add
+// compiler barriers.
namespace boost
{
namespace detail
{
- // Since VS2005 volatile reads always acquire
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
{
long const res=*x;
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
return res;
}
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
{
void* const res=*x;
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
return res;
}
- // Since VS2005 volatile writes always release
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
{
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
*x=value;
}
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
{
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
*x=value;
}
}
}
+#elif defined(_MSC_VER) && _MSC_VER >= 1700 && (defined(_M_ARM) || defined(_M_ARM64))
+
+#include <intrin.h>
+
+namespace boost
+{
+ namespace detail
+ {
+ inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
+ {
+ long const res=__iso_volatile_load32((const volatile __int32*)x);
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ return res;
+ }
+ inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
+ {
+ void* const res=
+#if defined(_M_ARM64)
+ __iso_volatile_load64((const volatile __int64*)x);
+#else
+ __iso_volatile_load32((const volatile __int32*)x);
+#endif
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ return res;
+ }
+
+ inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
+ {
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ __iso_volatile_store32((volatile __int32*)x, (__int32)value);
+ }
+ inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
+ {
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+ __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
+ BOOST_THREAD_DETAIL_COMPILER_BARRIER();
+#if defined(_M_ARM64)
+ __iso_volatile_store64((volatile __int64*)x, (__int64)value);
+#else
+ __iso_volatile_store32((volatile __int32*)x, (__int32)value);
+#endif
+ }
+ }
+}
+
+#elif defined(__GNUC__) && (((__GNUC__ * 100 + __GNUC_MINOR__) >= 407) || (defined(__clang__) && (__clang_major__ * 100 + __clang_minor__) >= 302))
+
+namespace boost
+{
+ namespace detail
+ {
+ inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
+ {
+ return __atomic_load_n((long*)x, __ATOMIC_ACQUIRE);
+ }
+ inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
+ {
+ return __atomic_load_n((void**)x, __ATOMIC_ACQUIRE);
+ }
+
+ inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
+ {
+ __atomic_store_n((long*)x, value, __ATOMIC_RELEASE);
+ }
+ inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
+ {
+ __atomic_store_n((void**)x, value, __ATOMIC_RELEASE);
+ }
+ }
+}
+
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
+namespace boost
+{
+ namespace detail
+ {
+ inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
+ {
+ long res;
+ __asm__ __volatile__ ("movl %1, %0" : "=r" (res) : "m" (*x) : "memory");
+ return res;
+ }
+ inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
+ {
+ void* res;
+#if defined(__x86_64__)
+ __asm__ __volatile__ ("movq %1, %0" : "=r" (res) : "m" (*x) : "memory");
+#else
+ __asm__ __volatile__ ("movl %1, %0" : "=r" (res) : "m" (*x) : "memory");
+#endif
+ return res;
+ }
+
+ inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
+ {
+ __asm__ __volatile__ ("movl %1, %0" : "=m" (*x) : "r" (value) : "memory");
+ }
+ inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
+ {
+#if defined(__x86_64__)
+ __asm__ __volatile__ ("movq %1, %0" : "=m" (*x) : "r" (value) : "memory");
+#else
+ __asm__ __volatile__ ("movl %1, %0" : "=m" (*x) : "r" (value) : "memory");
+#endif
+ }
+ }
+}
+
#else
namespace boost
@@ -53,19 +190,19 @@ namespace boost
{
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
{
- return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0);
+ return BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)x,0,0);
}
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
{
- return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
+ return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER((void**)x,0,0);
}
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
{
- BOOST_INTERLOCKED_EXCHANGE(x,value);
+ BOOST_INTERLOCKED_EXCHANGE((long*)x,value);
}
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
{
- BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value);
+ BOOST_INTERLOCKED_EXCHANGE_POINTER((void**)x,value);
}
}
}
diff --git a/boost/thread/win32/thread_primitives.hpp b/boost/thread/win32/thread_primitives.hpp
index c9e279faa0..133cc9c761 100644
--- a/boost/thread/win32/thread_primitives.hpp
+++ b/boost/thread/win32/thread_primitives.hpp
@@ -18,6 +18,7 @@
#include <boost/detail/interlocked.hpp>
#include <boost/detail/winapi/config.hpp>
//#include <boost/detail/winapi/synchronization.hpp>
+#include <boost/thread/win32/interlocked_read.hpp>
#include <algorithm>
#if BOOST_PLAT_WINDOWS_RUNTIME
@@ -244,19 +245,19 @@ namespace boost
// Borrowed from https://stackoverflow.com/questions/8211820/userland-interrupt-timer-access-such-as-via-kequeryinterrupttime-or-similar
inline ticks_type __stdcall GetTickCount64emulation()
{
- static volatile long count = 0xFFFFFFFF;
+ static long count = -1l;
unsigned long previous_count, current_tick32, previous_count_zone, current_tick32_zone;
ticks_type current_tick64;
- previous_count = (unsigned long) _InterlockedCompareExchange(&count, 0, 0);
+ previous_count = (unsigned long) boost::detail::interlocked_read_acquire(&count);
current_tick32 = GetTickCount();
- if(previous_count == 0xFFFFFFFF)
+ if(previous_count == (unsigned long)-1l)
{
// count has never been written
unsigned long initial_count;
initial_count = current_tick32 >> 28;
- previous_count = (unsigned long) _InterlockedCompareExchange(&count, initial_count, 0xFFFFFFFF);
+ previous_count = (unsigned long) _InterlockedCompareExchange(&count, (long)initial_count, -1l);
current_tick64 = initial_count;
current_tick64 <<= 28;
@@ -279,8 +280,9 @@ namespace boost
if(current_tick32_zone == previous_count_zone + 1 || (current_tick32_zone == 0 && previous_count_zone == 15))
{
// The top four bits of the 32-bit tick count have been incremented since count was last written.
- _InterlockedCompareExchange(&count, previous_count + 1, previous_count);
- current_tick64 = previous_count + 1;
+ unsigned long new_count = previous_count + 1;
+ _InterlockedCompareExchange(&count, (long)new_count, (long)previous_count);
+ current_tick64 = new_count;
current_tick64 <<= 28;
current_tick64 += current_tick32 & 0x0FFFFFFF;
return current_tick64;
diff --git a/boost/type_index/runtime_cast/register_runtime_class.hpp b/boost/type_index/runtime_cast/register_runtime_class.hpp
index 37ce686e32..995007487b 100644
--- a/boost/type_index/runtime_cast/register_runtime_class.hpp
+++ b/boost/type_index/runtime_cast/register_runtime_class.hpp
@@ -10,7 +10,8 @@
#define BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP
/// \file register_runtime_class.hpp
-/// \brief Contains the macro BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS
+/// \brief Contains the macros BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST and
+/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS
#include <boost/type_index.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
@@ -29,6 +30,8 @@ inline type_index runtime_class_construct_type_id(T const*) {
} // namespace detail
+}} // namespace boost::typeindex
+
/// @cond
#define BOOST_TYPE_INDEX_CHECK_BASE_(r, data, Base) \
@@ -44,6 +47,11 @@ inline type_index runtime_class_construct_type_id(T const*) {
/// boost::typeindex::runtime_cast to accurately convert between dynamic types of instances of
/// the current class.
///
+/// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS also adds support for boost::typeindex::type_id_runtime
+/// by including BOOST_TYPE_INDEX_REGISTER_CLASS. It is typical that these features are used together,
+/// but in the event that BOOST_TYPE_INDEX_REGISTER_CLASS is undesirable in the current class,
+/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST is provided.
+///
/// \b Example:
/// \code
/// struct base1 {
@@ -67,22 +75,64 @@ inline type_index runtime_class_construct_type_id(T const*) {
/// ...
///
/// base1* pb1 = get_object();
-/// if(derived2* pb2 = boost::typeindex::runtime_cast<derived2*>(pb1))
-/// { /* ... */ }
+/// if(derived2* pb2 = boost::typeindex::runtime_cast<derived2*>(pb1)) {
+/// assert(boost::typeindex::type_id_runtime(*pb1)) == boost::typeindex::type_id<derived2>());
+/// }
/// \endcode
///
/// \param base_class_seq A Boost.Preprocessor sequence of the current class' direct bases, or
-/// BOOST_PP_SEQ_NIL if this class has no direct base classes.
+/// BOOST_TYPE_INDEX_NO_BASE_CLASS if this class has no direct base classes.
#define BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(base_class_seq) \
- BOOST_TYPE_INDEX_REGISTER_CLASS \
+ BOOST_TYPE_INDEX_REGISTER_CLASS \
+ BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base_class_seq)
+
+/// \def BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST
+/// \brief Macro used to make a class compatible with boost::typeindex::runtime_cast without including
+/// support for boost::typeindex::type_id_runtime.
+///
+/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST is provided as an alternative to BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS
+/// in the event that support for boost::typeindex::type_id_runtime is undesirable.
+///
+/// \b Example:
+/// \code
+/// struct base1 {
+/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS)
+/// virtual ~base1();
+/// };
+///
+/// struct base2 {
+/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS)
+/// virtual ~base2();
+/// };
+///
+/// struct derived1 : base1 {
+/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base1))
+/// };
+///
+/// struct derived2 : base1, base2 {
+/// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base1)(base2))
+/// };
+///
+/// ...
+///
+/// base1* pb1 = get_object();
+/// if(derived2* pb2 = boost::typeindex::runtime_cast<derived2*>(pb1))
+/// { /* can't call boost::typeindex::type_id_runtime(*pb1) here */ }
+/// \endcode
+///
+/// \param base_class_seq A Boost.Preprocessor sequence of the current class' direct bases, or
+/// BOOST_TYPE_INDEX_NO_BASE_CLASS if this class has no direct base classes.
+#define BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base_class_seq) \
virtual void const* boost_type_index_find_instance_(boost::typeindex::type_index const& idx) const BOOST_NOEXCEPT { \
if(idx == boost::typeindex::detail::runtime_class_construct_type_id(this)) \
return this; \
BOOST_PP_SEQ_FOR_EACH(BOOST_TYPE_INDEX_CHECK_BASE_, _, base_class_seq) \
return NULL; \
}
-}} // namespace boost::typeindex
+/// \def BOOST_TYPE_INDEX_NO_BASE_CLASS
+/// \brief Instructs BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS and BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST
+/// that this class has no base classes.
#define BOOST_TYPE_INDEX_NO_BASE_CLASS BOOST_PP_SEQ_NIL
#endif // BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP
diff --git a/boost/type_index/stl_type_index.hpp b/boost/type_index/stl_type_index.hpp
index a5add88716..be28889962 100644
--- a/boost/type_index/stl_type_index.hpp
+++ b/boost/type_index/stl_type_index.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) Antony Polukhin, 2013-2015.
+// Copyright (c) Antony Polukhin, 2013-2017.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -174,7 +174,7 @@ inline std::string stl_type_index::pretty_name() const {
inline std::size_t stl_type_index::hash_code() const BOOST_NOEXCEPT {
-#if _MSC_VER > 1600 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__))
+#if (defined(_MSC_VER) && _MSC_VER > 1600) || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__))
return data_->hash_code();
#else
return boost::hash_range(raw_name(), raw_name() + std::strlen(raw_name()));
diff --git a/boost/type_traits.hpp b/boost/type_traits.hpp
index 7d651ce28d..93a992d38c 100644
--- a/boost/type_traits.hpp
+++ b/boost/type_traits.hpp
@@ -130,6 +130,7 @@
#include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/make_signed.hpp>
#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/type_traits/make_void.hpp>
#include <boost/type_traits/rank.hpp>
#include <boost/type_traits/remove_all_extents.hpp>
#include <boost/type_traits/remove_bounds.hpp>
diff --git a/boost/type_traits/detail/common_arithmetic_type.hpp b/boost/type_traits/detail/common_arithmetic_type.hpp
index 8c091583c5..a7aff03929 100644
--- a/boost/type_traits/detail/common_arithmetic_type.hpp
+++ b/boost/type_traits/detail/common_arithmetic_type.hpp
@@ -46,7 +46,7 @@ template<> struct arithmetic_type<3>
#endif
// There are five standard signed integer types:
-// “signed charâ€, “short intâ€, “intâ€, “long intâ€, and “long long intâ€.
+// "signed char", "short int", "int", "long int", and "long long int".
template<> struct arithmetic_type<4>
{
@@ -79,8 +79,8 @@ template<> struct arithmetic_type<8>
};
// For each of the standard signed integer types, there exists a corresponding
-// (but different) standard unsigned integer type: “unsigned charâ€, “unsigned short intâ€,
-// “unsigned intâ€, “unsigned long intâ€, and “unsigned long long intâ€
+// (but different) standard unsigned integer type: "unsigned char", "unsigned short int",
+// "unsigned int", "unsigned long int", and "unsigned long long int"
template<> struct arithmetic_type<9>
{
diff --git a/boost/type_traits/is_rvalue_reference.hpp b/boost/type_traits/is_rvalue_reference.hpp
index 50e88edee0..a48edb5140 100644
--- a/boost/type_traits/is_rvalue_reference.hpp
+++ b/boost/type_traits/is_rvalue_reference.hpp
@@ -1,5 +1,5 @@
-// (C) John Maddock 2010.
+// (C) Copyright John Maddock 2010.
// 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).
diff --git a/boost/type_traits/make_void.hpp b/boost/type_traits/make_void.hpp
new file mode 100644
index 0000000000..f48823b059
--- /dev/null
+++ b/boost/type_traits/make_void.hpp
@@ -0,0 +1,52 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+<glenjofe -at- gmail.com>
+
+Distributed under the Boost Software License,
+Version 1.0. (See accompanying file LICENSE_1_0.txt
+or copy at http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_TT_MAKE_VOID_HPP_INCLUDED
+#define BOOST_TT_MAKE_VOID_HPP_INCLUDED
+
+#include <boost/config.hpp>
+
+namespace boost {
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+template<class...>
+struct make_void {
+ typedef void type;
+};
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+template<class... Ts>
+using void_t = typename make_void<Ts...>::type;
+#endif
+
+#else /* BOOST_NO_CXX11_VARIADIC_TEMPLATES */
+
+template<class = void,
+ class = void,
+ class = void,
+ class = void,
+ class = void>
+struct make_void {
+ typedef void type;
+};
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+template<class A = void,
+ class B = void,
+ class C = void,
+ class D = void,
+ class E = void>
+using void_t = typename make_void<A, B, C, D, E>::type;
+#endif
+
+#endif
+
+} /* boost */
+
+#endif
diff --git a/boost/unordered/detail/allocate.hpp b/boost/unordered/detail/allocate.hpp
deleted file mode 100644
index 8e4f86941a..0000000000
--- a/boost/unordered/detail/allocate.hpp
+++ /dev/null
@@ -1,1393 +0,0 @@
-
-// Copyright 2005-2011 Daniel James.
-// Copyright 2009 Pablo Halpern.
-// Distributed under the Boost Software License, Version 1.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/unordered for documentation
-
-#ifndef BOOST_UNORDERED_ALLOCATE_HPP
-#define BOOST_UNORDERED_ALLOCATE_HPP
-
-#include <boost/config.hpp>
-#if defined(BOOST_HAS_PRAGMA_ONCE)
-#pragma once
-#endif
-
-// Some of these includes are required for other detail headers.
-#include <boost/unordered/detail/fwd.hpp>
-#include <boost/move/move.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>
-#include <boost/preprocessor/repetition/repeat_from_to.hpp>
-#include <boost/type_traits/is_class.hpp>
-#include <boost/type_traits/add_lvalue_reference.hpp>
-#include <boost/type_traits/aligned_storage.hpp>
-#include <boost/type_traits/alignment_of.hpp>
-#include <boost/type_traits/is_nothrow_move_constructible.hpp>
-#include <boost/type_traits/is_nothrow_move_assignable.hpp>
-#include <boost/tuple/tuple.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/utility/addressof.hpp>
-#include <boost/detail/no_exceptions_support.hpp>
-#include <boost/detail/select_type.hpp>
-#include <boost/swap.hpp>
-#include <boost/assert.hpp>
-#include <boost/limits.hpp>
-#include <iterator>
-#include <utility>
-#include <cmath>
-
-#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
-#include <tuple>
-#endif
-
-#if defined(BOOST_MSVC)
-#pragma warning(push)
-#pragma warning(disable:4512) // assignment operator could not be generated.
-#pragma warning(disable:4345) // behavior change: an object of POD type
- // constructed with an initializer of the form ()
- // will be default-initialized.
-#endif
-
-// Maximum number of arguments supported by emplace + 1.
-#define BOOST_UNORDERED_EMPLACE_LIMIT 11
-
-namespace boost { namespace unordered { namespace detail {
-
- ////////////////////////////////////////////////////////////////////////////
- // Bits and pieces for implementing traits
-
- template <typename T> typename boost::add_lvalue_reference<T>::type make();
- struct choice9 { typedef char (&type)[9]; };
- struct choice8 : choice9 { typedef char (&type)[8]; };
- struct choice7 : choice8 { typedef char (&type)[7]; };
- struct choice6 : choice7 { typedef char (&type)[6]; };
- struct choice5 : choice6 { typedef char (&type)[5]; };
- struct choice4 : choice5 { typedef char (&type)[4]; };
- struct choice3 : choice4 { typedef char (&type)[3]; };
- struct choice2 : choice3 { typedef char (&type)[2]; };
- struct choice1 : choice2 { typedef char (&type)[1]; };
- choice1 choose();
-
- typedef choice1::type yes_type;
- typedef choice2::type no_type;
-
- struct private_type
- {
- private_type const &operator,(int) const;
- };
-
- template <typename T>
- no_type is_private_type(T const&);
- yes_type is_private_type(private_type const&);
-
- 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) {
- return const_cast<T*>(x);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // emplace_args
- //
- // Either forwarding variadic arguments, or storing the arguments in
- // emplace_args##n
-
-#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
-
-#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
-
-#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
- typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \
- BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
-
-#else
-
-#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
- typedef typename boost::add_lvalue_reference<BOOST_PP_CAT(A, n)>::type \
- BOOST_PP_CAT(Arg, n); \
- BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
-
-#endif
-
-template <typename A0>
-struct emplace_args1
-{
- BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
-
- emplace_args1(Arg0 b0) : a0(b0) {}
-};
-
-template <typename A0>
-inline emplace_args1<A0> create_emplace_args(
- BOOST_FWD_REF(A0) b0)
-{
- emplace_args1<A0> e(b0);
- return e;
-}
-
-template <typename A0, typename A1>
-struct emplace_args2
-{
- BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
- BOOST_UNORDERED_EARGS_MEMBER(1, 1, _)
-
- emplace_args2(Arg0 b0, Arg1 b1) : a0(b0), a1(b1) {}
-};
-
-template <typename A0, typename A1>
-inline emplace_args2<A0, A1> create_emplace_args(
- BOOST_FWD_REF(A0) b0,
- BOOST_FWD_REF(A1) b1)
-{
- emplace_args2<A0, A1> e(b0, b1);
- return e;
-}
-
-template <typename A0, typename A1, typename A2>
-struct emplace_args3
-{
- BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
- BOOST_UNORDERED_EARGS_MEMBER(1, 1, _)
- BOOST_UNORDERED_EARGS_MEMBER(1, 2, _)
-
- emplace_args3(Arg0 b0, Arg1 b1, Arg2 b2) : a0(b0), a1(b1), a2(b2) {}
-};
-
-template <typename A0, typename A1, typename A2>
-inline emplace_args3<A0, A1, A2> create_emplace_args(
- BOOST_FWD_REF(A0) b0,
- BOOST_FWD_REF(A1) b1,
- BOOST_FWD_REF(A2) b2)
-{
- emplace_args3<A0, A1, A2> e(b0, b1, b2);
- return e;
-}
-
-#define BOOST_UNORDERED_FWD_PARAM(z, n, a) \
- BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n)
-
-#define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \
- boost::forward<BOOST_PP_CAT(A,i)>(BOOST_PP_CAT(a,i))
-
-#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
-BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
-
-#define BOOST_UNORDERED_EARGS(z, n, _) \
- template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
- struct BOOST_PP_CAT(emplace_args, n) \
- { \
- BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) \
- BOOST_PP_CAT(emplace_args, n) ( \
- BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, b) \
- ) : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \
- {} \
- \
- }; \
- \
- template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
- inline BOOST_PP_CAT(emplace_args, n) < \
- BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
- > create_emplace_args( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, b) \
- ) \
- { \
- BOOST_PP_CAT(emplace_args, n) < \
- BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
- > e(BOOST_PP_ENUM_PARAMS_Z(z, n, b)); \
- return e; \
- }
-
-BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
- _)
-
-#undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS
-#undef BOOST_UNORDERED_EARGS_MEMBER
-#undef BOOST_UNORDERED_EARGS_INIT
-
-#endif
-
-}}}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Pick which version of allocator_traits to use
-//
-// 0 = Own partial implementation
-// 1 = std::allocator_traits
-// 2 = boost::container::allocator_traits
-
-#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
-# if !defined(BOOST_NO_CXX11_ALLOCATOR)
-# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
-# elif defined(BOOST_MSVC)
-# if BOOST_MSVC < 1400
- // Use container's allocator_traits for older versions of Visual
- // C++ as I don't test with them.
-# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
-# endif
-# endif
-#endif
-
-#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
-# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Some utilities for implementing allocator_traits, but useful elsewhere so
-// they're always defined.
-
-#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
-# include <type_traits>
-#endif
-
-namespace boost { namespace unordered { namespace detail {
-
- ////////////////////////////////////////////////////////////////////////////
- // Integral_constrant, true_type, false_type
- //
- // Uses the standard versions if available.
-
-#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
-
- using std::integral_constant;
- using std::true_type;
- using std::false_type;
-
-#else
-
- template <typename T, T Value>
- struct integral_constant { enum { value = Value }; };
-
- typedef boost::unordered::detail::integral_constant<bool, true> true_type;
- typedef boost::unordered::detail::integral_constant<bool, false> false_type;
-
-#endif
-
- ////////////////////////////////////////////////////////////////////////////
- // Explicitly call a destructor
-
-#if defined(BOOST_MSVC)
-#pragma warning(push)
-#pragma warning(disable:4100) // unreferenced formal parameter
-#endif
-
- namespace func {
- template <class T>
- inline void destroy(T* x) {
- x->~T();
- }
- }
-
-#if defined(BOOST_MSVC)
-#pragma warning(pop)
-#endif
-
- ////////////////////////////////////////////////////////////////////////////
- // Expression test mechanism
- //
- // When SFINAE expressions are available, define
- // BOOST_UNORDERED_HAS_FUNCTION which can check if a function call is
- // supported by a class, otherwise define BOOST_UNORDERED_HAS_MEMBER which
- // can detect if a class has the specified member, but not that it has the
- // correct type, this is good enough for a passable impression of
- // allocator_traits.
-
-#if !defined(BOOST_NO_SFINAE_EXPR)
-
- template <typename T, long unsigned int> struct expr_test;
- template <typename T> struct expr_test<T, sizeof(char)> : T {};
-
-# define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
- template <typename U> \
- static typename boost::unordered::detail::expr_test< \
- BOOST_PP_CAT(choice, result), \
- sizeof(for_expr_test(( \
- (expression), \
- 0)))>::type test( \
- BOOST_PP_CAT(choice, count))
-
-# define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
- template <typename U> \
- static BOOST_PP_CAT(choice, result)::type test( \
- BOOST_PP_CAT(choice, count))
-
-# define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
- struct BOOST_PP_CAT(has_, name) \
- { \
- template <typename U> static char for_expr_test(U const&); \
- BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
- boost::unordered::detail::make< thing >().name args); \
- BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
- \
- enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };\
- }
-
-#else
-
- template <typename T> struct identity { typedef T type; };
-
-# define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
- \
- typedef typename boost::unordered::detail::identity<member>::type \
- BOOST_PP_CAT(check, count); \
- \
- template <BOOST_PP_CAT(check, count) e> \
- struct BOOST_PP_CAT(test, count) { \
- typedef BOOST_PP_CAT(choice, result) type; \
- }; \
- \
- template <class U> static typename \
- BOOST_PP_CAT(test, count)<&U::name>::type \
- test(BOOST_PP_CAT(choice, count))
-
-# define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
- template <class U> static BOOST_PP_CAT(choice, result)::type \
- test(BOOST_PP_CAT(choice, count))
-
-# define BOOST_UNORDERED_HAS_MEMBER(name) \
- struct BOOST_PP_CAT(has_, name) \
- { \
- struct impl { \
- struct base_mixin { int name; }; \
- struct base : public T, public base_mixin {}; \
- \
- BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \
- BOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \
- \
- enum { value = sizeof(choice2::type) == \
- sizeof(test<base>(choose())) \
- }; \
- }; \
- \
- enum { value = impl::value }; \
- }
-
-#endif
-
-}}}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Allocator traits
-//
-// First our implementation, then later light wrappers around the alternatives
-
-#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
-
-# include <boost/limits.hpp>
-# include <boost/utility/enable_if.hpp>
-# include <boost/pointer_to_other.hpp>
-# if defined(BOOST_NO_SFINAE_EXPR)
-# include <boost/type_traits/is_same.hpp>
-# endif
-
-# 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 {
-
- template <typename Alloc, typename T>
- struct rebind_alloc;
-
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-
- template <template<typename, typename...> class Alloc,
- typename U, typename T, typename... Args>
- struct rebind_alloc<Alloc<U, Args...>, T>
- {
- typedef Alloc<T, Args...> type;
- };
-
-#else
-
- template <
- template<typename> class Alloc,
- typename U, typename T>
- struct rebind_alloc<Alloc<U>, T>
- {
- typedef Alloc<T> type;
- };
-
- template <
- template<typename, typename> class Alloc,
- typename U, typename T,
- typename A0>
- struct rebind_alloc<Alloc<U, A0>, T>
- {
- typedef Alloc<T, A0> type;
- };
-
- template <
- template<typename, typename, typename> class Alloc,
- typename U, typename T,
- typename A0, typename A1>
- struct rebind_alloc<Alloc<U, A0, A1>, T>
- {
- typedef Alloc<T, A0, A1> type;
- };
-
-#endif
-
- template <typename Alloc, typename T>
- struct rebind_wrap
- {
- template <typename X>
- static choice1::type test(choice1,
- typename X::BOOST_NESTED_TEMPLATE rebind<T>::other* = 0);
- template <typename X>
- static choice2::type test(choice2, void* = 0);
-
- enum { value = (1 == sizeof(test<Alloc>(choose()))) };
-
- struct fallback {
- template <typename U>
- struct rebind {
- typedef typename rebind_alloc<Alloc, T>::type other;
- };
- };
-
- typedef typename boost::detail::if_true<value>::
- BOOST_NESTED_TEMPLATE then<Alloc, fallback>
- ::type::BOOST_NESTED_TEMPLATE rebind<T>::other type;
- };
-
-# if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
-
-# define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
- template <typename Tp, typename Default> \
- struct default_type_ ## tname { \
- \
- template <typename X> \
- static choice1::type test(choice1, typename X::tname* = 0); \
- \
- template <typename X> \
- static choice2::type test(choice2, void* = 0); \
- \
- struct DefaultWrap { typedef Default tname; }; \
- \
- enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
- \
- typedef typename boost::detail::if_true<value>:: \
- BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
- ::type::tname type; \
- }
-
-# else
-
- template <typename T, typename T2>
- struct sfinae : T2 {};
-
-# define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
- template <typename Tp, typename Default> \
- struct default_type_ ## tname { \
- \
- template <typename X> \
- static typename boost::unordered::detail::sfinae< \
- typename X::tname, choice1>::type \
- test(choice1); \
- \
- template <typename X> \
- static choice2::type test(choice2); \
- \
- struct DefaultWrap { typedef Default tname; }; \
- \
- enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
- \
- typedef typename boost::detail::if_true<value>:: \
- BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
- ::type::tname type; \
- }
-
-# endif
-
-# define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
- typename default_type_ ## tname<T, arg>::type
-
- BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
- BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
- BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer);
- BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer);
- BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type);
- BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type);
- BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
- BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
- BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
-
-# if !defined(BOOST_NO_SFINAE_EXPR)
-
- template <typename T>
- BOOST_UNORDERED_HAS_FUNCTION(
- select_on_container_copy_construction, U const, (), 0
- );
-
- template <typename T>
- BOOST_UNORDERED_HAS_FUNCTION(
- max_size, U const, (), 0
- );
-
-# if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-
- template <typename T, typename ValueType, typename... Args>
- BOOST_UNORDERED_HAS_FUNCTION(
- construct, U, (
- boost::unordered::detail::make<ValueType*>(),
- boost::unordered::detail::make<Args const>()...), 2
- );
-
-# else
-
- template <typename T, typename ValueType>
- BOOST_UNORDERED_HAS_FUNCTION(
- construct, U, (
- boost::unordered::detail::make<ValueType*>(),
- boost::unordered::detail::make<ValueType const>()), 2
- );
-
-# endif
-
- template <typename T, typename ValueType>
- BOOST_UNORDERED_HAS_FUNCTION(
- destroy, U, (boost::unordered::detail::make<ValueType*>()), 1
- );
-
-# else
-
- template <typename T>
- BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
-
- template <typename T>
- BOOST_UNORDERED_HAS_MEMBER(max_size);
-
- template <typename T, typename ValueType>
- BOOST_UNORDERED_HAS_MEMBER(construct);
-
- template <typename T, typename ValueType>
- BOOST_UNORDERED_HAS_MEMBER(destroy);
-
-# endif
-
- namespace func
- {
-
- template <typename Alloc>
- inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
- typename boost::enable_if_c<
- boost::unordered::detail::
- has_select_on_container_copy_construction<Alloc>::value, void*
- >::type = 0)
- {
- return rhs.select_on_container_copy_construction();
- }
-
- template <typename Alloc>
- inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
- typename boost::disable_if_c<
- boost::unordered::detail::
- has_select_on_container_copy_construction<Alloc>::value, void*
- >::type = 0)
- {
- return rhs;
- }
-
- template <typename SizeType, typename Alloc>
- inline SizeType call_max_size(const Alloc& a,
- typename boost::enable_if_c<
- boost::unordered::detail::has_max_size<Alloc>::value, void*
- >::type = 0)
- {
- return a.max_size();
- }
-
- template <typename SizeType, typename Alloc>
- inline SizeType call_max_size(const Alloc&, typename boost::disable_if_c<
- boost::unordered::detail::has_max_size<Alloc>::value, void*
- >::type = 0)
- {
- return (std::numeric_limits<SizeType>::max)();
- }
-
- } // namespace func.
-
- template <typename Alloc>
- struct allocator_traits
- {
- typedef Alloc allocator_type;
- typedef typename Alloc::value_type value_type;
-
- typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*)
- pointer;
-
- template <typename T>
- struct pointer_to_other : boost::pointer_to_other<pointer, T> {};
-
- typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
- typename pointer_to_other<const value_type>::type)
- const_pointer;
-
- //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
- // typename pointer_to_other<void>::type)
- // void_pointer;
- //
- //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
- // typename pointer_to_other<const void>::type)
- // const_void_pointer;
-
- typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
- std::ptrdiff_t) difference_type;
-
- typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
- size_type;
-
-#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
- template <typename T>
- using rebind_alloc = typename rebind_wrap<Alloc, T>::type;
-
- template <typename T>
- using rebind_traits =
- boost::unordered::detail::allocator_traits<rebind_alloc<T> >;
-#endif
-
- static pointer allocate(Alloc& a, size_type n)
- { return a.allocate(n); }
-
- // I never use this, so I'll just comment it out for now.
- //
- //static pointer allocate(Alloc& a, size_type n,
- // const_void_pointer hint)
- // { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
-
- static void deallocate(Alloc& a, pointer p, size_type n)
- { a.deallocate(p, n); }
-
- public:
-
-# if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
-
- template <typename T, typename... Args>
- static typename boost::enable_if_c<
- boost::unordered::detail::has_construct<Alloc, T, Args...>
- ::value>::type
- construct(Alloc& a, T* p, BOOST_FWD_REF(Args)... x)
- {
- a.construct(p, boost::forward<Args>(x)...);
- }
-
- template <typename T, typename... Args>
- static typename boost::disable_if_c<
- boost::unordered::detail::has_construct<Alloc, T, Args...>
- ::value>::type
- construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x)
- {
- new (static_cast<void*>(p)) T(boost::forward<Args>(x)...);
- }
-
- template <typename T>
- static typename boost::enable_if_c<
- boost::unordered::detail::has_destroy<Alloc, T>::value>::type
- destroy(Alloc& a, T* p)
- {
- a.destroy(p);
- }
-
- template <typename T>
- static typename boost::disable_if_c<
- boost::unordered::detail::has_destroy<Alloc, T>::value>::type
- destroy(Alloc&, T* p)
- {
- boost::unordered::detail::func::destroy(p);
- }
-
-# elif !defined(BOOST_NO_SFINAE_EXPR)
-
- template <typename T>
- static typename boost::enable_if_c<
- boost::unordered::detail::has_construct<Alloc, T>::value>::type
- construct(Alloc& a, T* p, T const& x)
- {
- a.construct(p, x);
- }
-
- template <typename T>
- static typename boost::disable_if_c<
- boost::unordered::detail::has_construct<Alloc, T>::value>::type
- construct(Alloc&, T* p, T const& x)
- {
- new (static_cast<void*>(p)) T(x);
- }
-
- template <typename T>
- static typename boost::enable_if_c<
- boost::unordered::detail::has_destroy<Alloc, T>::value>::type
- destroy(Alloc& a, T* p)
- {
- a.destroy(p);
- }
-
- template <typename T>
- static typename boost::disable_if_c<
- boost::unordered::detail::has_destroy<Alloc, T>::value>::type
- destroy(Alloc&, T* p)
- {
- boost::unordered::detail::func::destroy(p);
- }
-
-# else
-
- // If we don't have SFINAE expressions, only call construct for the
- // copy constructor for the allocator's value_type - as that's
- // the only construct method that old fashioned allocators support.
-
- template <typename T>
- static void construct(Alloc& a, T* p, T const& x,
- typename boost::enable_if_c<
- boost::unordered::detail::has_construct<Alloc, T>::value &&
- boost::is_same<T, value_type>::value,
- void*>::type = 0)
- {
- a.construct(p, x);
- }
-
- template <typename T>
- static void construct(Alloc&, T* p, T const& x,
- typename boost::disable_if_c<
- boost::unordered::detail::has_construct<Alloc, T>::value &&
- boost::is_same<T, value_type>::value,
- void*>::type = 0)
- {
- new (static_cast<void*>(p)) T(x);
- }
-
- template <typename T>
- static void destroy(Alloc& a, T* p,
- typename boost::enable_if_c<
- boost::unordered::detail::has_destroy<Alloc, T>::value &&
- boost::is_same<T, value_type>::value,
- void*>::type = 0)
- {
- a.destroy(p);
- }
-
- template <typename T>
- static void destroy(Alloc&, T* p,
- typename boost::disable_if_c<
- boost::unordered::detail::has_destroy<Alloc, T>::value &&
- boost::is_same<T, value_type>::value,
- void*>::type = 0)
- {
- boost::unordered::detail::func::destroy(p);
- }
-
-# endif
-
- static size_type max_size(const Alloc& a)
- {
- return boost::unordered::detail::func::
- call_max_size<size_type>(a);
- }
-
- // Allocator propagation on construction
-
- static Alloc select_on_container_copy_construction(Alloc const& rhs)
- {
- return boost::unordered::detail::func::
- call_select_on_container_copy_construction(rhs);
- }
-
- // Allocator propagation on assignment and swap.
- // Return true if lhs is modified.
- typedef BOOST_UNORDERED_DEFAULT_TYPE(
- Alloc, propagate_on_container_copy_assignment, false_type)
- propagate_on_container_copy_assignment;
- typedef BOOST_UNORDERED_DEFAULT_TYPE(
- Alloc,propagate_on_container_move_assignment, false_type)
- propagate_on_container_move_assignment;
- typedef BOOST_UNORDERED_DEFAULT_TYPE(
- Alloc,propagate_on_container_swap,false_type)
- propagate_on_container_swap;
- };
-}}}
-
-# undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
-# undef BOOST_UNORDERED_DEFAULT_TYPE
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// std::allocator_traits
-
-#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
-
-# include <memory>
-
-# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
-
-namespace boost { namespace unordered { namespace detail {
-
- template <typename Alloc>
- struct allocator_traits : std::allocator_traits<Alloc> {};
-
- template <typename Alloc, typename T>
- struct rebind_wrap
- {
- typedef typename std::allocator_traits<Alloc>::
- template rebind_alloc<T> type;
- };
-}}}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// boost::container::allocator_traits
-
-#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
-
-# include <boost/container/allocator_traits.hpp>
-
-# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
-
-namespace boost { namespace unordered { namespace detail {
-
- template <typename Alloc>
- struct allocator_traits :
- boost::container::allocator_traits<Alloc> {};
-
- template <typename Alloc, typename T>
- struct rebind_wrap :
- boost::container::allocator_traits<Alloc>::
- template portable_rebind_alloc<T>
- {};
-
-}}}
-
-#else
-
-#error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
-
-#endif
-
-
-namespace boost { namespace unordered { namespace detail { namespace func {
-
- ////////////////////////////////////////////////////////////////////////////
- // call_construct
-
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-
-# if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
-
- 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
-
- template <typename Alloc, typename T, typename... Args>
- inline void call_construct(Alloc&, 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
-
-#else
- template <typename Alloc, typename T>
- inline void call_construct(Alloc&, 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)
- {
- 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);
- }
-
-#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_)
-
-# 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& alloc, T* ptr, \
- namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
- { \
- boost::unordered::detail::func::call_construct(alloc, ptr, \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
- ); \
- }
-
-# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
- namespace_ get<n>(x)
-
-#elif !defined(__SUNPRO_CC)
-
-# 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_)
-
-# 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_) \
- ); \
- }
-
-# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
- namespace_ get<n>(x)
-
-#else
-
- 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_) \
- 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) \
- { \
- 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
-
-#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
-#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
-#undef BOOST_UNORDERED_GET_TUPLE_ARG
-
-#if defined(__SUNPRO_CC)
-
- template <typename Alloc, typename T, typename Tuple>
- void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
- {
- construct_from_tuple_impl(
- boost::unordered::detail::func::length<
- boost::tuples::length<Tuple>::value>(),
- alloc, ptr, x);
- }
-
-#endif
-
- ////////////////////////////////////////////////////////////////////////////
- // Trait to check for piecewise construction.
-
- template <typename A0>
- struct use_piecewise {
- static choice1::type test(choice1,
- boost::unordered::piecewise_construct_t);
-
- static choice2::type test(choice2, ...);
-
- enum { value = sizeof(choice1::type) ==
- sizeof(test(choose(), boost::unordered::detail::make<A0>())) };
- };
-
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-
- ////////////////////////////////////////////////////////////////////////////
- // 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(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.
-
- template <typename Alloc, typename A, typename B,
- typename A0, typename A1, typename A2>
- inline typename enable_if<use_piecewise<A0>, 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::unordered::detail::func::const_cast_pointer(
- boost::addressof(address->first)),
- boost::forward<A1>(a1));
- boost::unordered::detail::func::construct_from_tuple(alloc,
- boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(address->second)),
- boost::forward<A2>(a2));
- }
-
-#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
-
- ////////////////////////////////////////////////////////////////////////////
- // Construct from emplace_args
-
- // Explicitly write out first three overloads for the sake of sane
- // error messages.
-
- template <typename Alloc, typename T, typename A0>
- inline void construct_from_args(Alloc&, T* address,
- emplace_args1<A0> const& args)
- {
- new((void*) address) T(boost::forward<A0>(args.a0));
- }
-
- template <typename Alloc, typename T, typename A0, typename A1>
- inline void construct_from_args(Alloc&, T* address,
- emplace_args2<A0, A1> const& args)
- {
- new((void*) address) T(
- boost::forward<A0>(args.a0),
- boost::forward<A1>(args.a1)
- );
- }
-
- template <typename Alloc, typename T, typename A0, typename A1, typename A2>
- inline void construct_from_args(Alloc&, T* address,
- emplace_args3<A0, A1, A2> const& args)
- {
- new((void*) address) T(
- boost::forward<A0>(args.a0),
- boost::forward<A1>(args.a1),
- boost::forward<A2>(args.a2)
- );
- }
-
- // Use a macro for the rest.
-
-#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
- template < \
- typename Alloc, typename T, \
- BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
- > \
- inline void construct_from_args(Alloc&, T* address, \
- boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
- BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
- > const& args) \
- { \
- new((void*) address) T( \
- BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \
- args.a)); \
- }
-
- BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_CONSTRUCT_IMPL, _)
-
-#undef BOOST_UNORDERED_CONSTRUCT_IMPL
-
- // Construct with piece_construct
-
- template <typename Alloc, typename A, typename B,
- typename A0, typename A1, typename A2>
- inline void construct_from_args(Alloc& alloc, std::pair<A, B>* address,
- boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
- 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);
- boost::unordered::detail::func::construct_from_tuple(alloc,
- boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(address->second)),
- args.a2);
- }
-
-#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
-
-}}}}
-
-namespace boost { namespace unordered { namespace detail {
-
- ///////////////////////////////////////////////////////////////////
- //
- // Node construction
-
- template <typename NodeAlloc>
- struct node_constructor
- {
- typedef NodeAlloc node_allocator;
- typedef boost::unordered::detail::allocator_traits<NodeAlloc>
- node_allocator_traits;
- typedef typename node_allocator_traits::value_type node;
- typedef typename node_allocator_traits::pointer node_pointer;
- typedef typename node::value_type value_type;
-
- node_allocator& alloc_;
- node_pointer node_;
- bool node_constructed_;
-
- node_constructor(node_allocator& n) :
- alloc_(n),
- node_(),
- node_constructed_(false)
- {
- }
-
- ~node_constructor();
-
- void create_node();
-
- // no throw
- node_pointer release()
- {
- BOOST_ASSERT(node_ && node_constructed_);
- node_pointer p = node_;
- node_ = node_pointer();
- return p;
- }
-
- void reclaim(node_pointer p) {
- BOOST_ASSERT(!node_);
- node_ = p;
- node_constructed_ = true;
- boost::unordered::detail::func::call_destroy(alloc_,
- node_->value_ptr());
- }
-
- private:
- node_constructor(node_constructor const&);
- node_constructor& operator=(node_constructor const&);
- };
-
- template <typename Alloc>
- node_constructor<Alloc>::~node_constructor()
- {
- if (node_) {
- if (node_constructed_) {
- boost::unordered::detail::func::destroy(
- boost::addressof(*node_));
- }
-
- node_allocator_traits::deallocate(alloc_, node_, 1);
- }
- }
-
- 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;
- }
-
- template <typename NodeAlloc>
- struct node_tmp
- {
- typedef boost::unordered::detail::allocator_traits<NodeAlloc>
- node_allocator_traits;
- typedef typename node_allocator_traits::pointer node_pointer;
-
- NodeAlloc& alloc_;
- node_pointer node_;
-
- explicit node_tmp(node_pointer n, NodeAlloc& a):
- alloc_(a),
- node_(n)
- {
- }
-
- ~node_tmp();
-
- // no throw
- node_pointer release()
- {
- node_pointer p = node_;
- node_ = node_pointer();
- return p;
- }
- };
-
- 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_));
- node_allocator_traits::deallocate(alloc_, node_, 1);
- }
- }
-}}}
-
-namespace boost { namespace unordered { namespace detail { namespace func {
-
- // Some nicer construct_node functions, might try to
- // improve implementation later.
-
- template <typename Alloc, BOOST_UNORDERED_EMPLACE_TEMPLATE>
- inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
- construct_node_from_args(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS)
- {
- node_constructor<Alloc> a(alloc);
- a.create_node();
- construct_from_args(alloc, a.node_->value_ptr(),
- BOOST_UNORDERED_EMPLACE_FORWARD);
- return a.release();
- }
-
- template <typename Alloc, typename U>
- inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
- 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));
- return a.release();
- }
-
- // TODO: When possible, it might be better to use std::pair's
- // constructor for std::piece_construct with std::tuple.
- 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::call_construct(alloc,
- boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(a.node_->value_ptr()->second)));
- 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::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::call_construct(alloc,
- boost::unordered::detail::func::const_cast_pointer(
- boost::addressof(a.node_->value_ptr()->second)),
- boost::forward<Mapped>(m));
- return a.release();
- }
-}}}}
-
-#if defined(BOOST_MSVC)
-#pragma warning(pop)
-#endif
-
-#endif
diff --git a/boost/unordered/detail/buckets.hpp b/boost/unordered/detail/buckets.hpp
deleted file mode 100644
index bd9a5cbb1e..0000000000
--- a/boost/unordered/detail/buckets.hpp
+++ /dev/null
@@ -1,774 +0,0 @@
-
-// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2011 Daniel James
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
-#define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
-
-#include <boost/config.hpp>
-#if defined(BOOST_HAS_PRAGMA_ONCE)
-#pragma once
-#endif
-
-#include <boost/unordered/detail/util.hpp>
-#include <boost/unordered/detail/allocate.hpp>
-
-namespace boost { namespace unordered { 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;
-
-}}}
-
-// The 'iterator_detail' namespace was a misguided attempt at avoiding ADL
-// in the detail namespace. It didn't work because the template parameters
-// were in detail. I'm not changing it at the moment to be safe. I might
-// do in the future if I change the iterator types.
-namespace boost { namespace unordered { namespace iterator_detail {
-
- ////////////////////////////////////////////////////////////////////////////
- // Iterators
- //
- // all no throw
-
- 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;
-
- // Local Iterators
- //
- // all no throw
-
- template <typename Node, typename Policy>
- 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>
- friend struct boost::unordered::iterator_detail::cl_iterator;
- private:
-#endif
- typedef typename Node::node_pointer node_pointer;
- node_pointer ptr_;
- std::size_t bucket_;
- std::size_t bucket_count_;
-
- public:
-
- typedef typename Node::value_type value_type;
-
- l_iterator() BOOST_NOEXCEPT : ptr_() {}
-
- l_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT
- : ptr_(n), bucket_(b), bucket_count_(c) {}
-
- value_type& operator*() const {
- return ptr_->value();
- }
-
- value_type* operator->() const {
- return ptr_->value_ptr();
- }
-
- l_iterator& operator++() {
- ptr_ = static_cast<node_pointer>(ptr_->next_);
- if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_)
- != bucket_)
- ptr_ = node_pointer();
- return *this;
- }
-
- l_iterator operator++(int) {
- l_iterator tmp(*this);
- ++(*this);
- return tmp;
- }
-
- bool operator==(l_iterator x) const BOOST_NOEXCEPT {
- return ptr_ == x.ptr_;
- }
-
- bool operator!=(l_iterator x) const BOOST_NOEXCEPT {
- return ptr_ != x.ptr_;
- }
- };
-
- template <typename Node, typename Policy>
- 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>;
- private:
-
- typedef typename Node::node_pointer node_pointer;
- node_pointer ptr_;
- std::size_t bucket_;
- std::size_t bucket_count_;
-
- public:
-
- typedef typename Node::value_type value_type;
-
- cl_iterator() BOOST_NOEXCEPT : ptr_() {}
-
- cl_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
- ptr_(n), bucket_(b), bucket_count_(c) {}
-
- cl_iterator(boost::unordered::iterator_detail::l_iterator<
- Node, Policy> const& x) BOOST_NOEXCEPT :
- ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
- {}
-
- value_type const& operator*() const {
- return ptr_->value();
- }
-
- value_type const* operator->() const {
- return ptr_->value_ptr();
- }
-
- cl_iterator& operator++() {
- ptr_ = static_cast<node_pointer>(ptr_->next_);
- if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_)
- != bucket_)
- ptr_ = node_pointer();
- return *this;
- }
-
- cl_iterator operator++(int) {
- cl_iterator tmp(*this);
- ++(*this);
- return tmp;
- }
-
- friend bool operator==(cl_iterator const& x, cl_iterator const& y)
- BOOST_NOEXCEPT
- {
- return x.ptr_ == y.ptr_;
- }
-
- friend bool operator!=(cl_iterator const& x, cl_iterator const& y)
- BOOST_NOEXCEPT
- {
- return x.ptr_ != y.ptr_;
- }
- };
-
- template <typename Node>
- struct 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>
- 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
- typedef typename Node::node_pointer node_pointer;
- node_pointer node_;
-
- public:
-
- typedef typename Node::value_type value_type;
-
- iterator() BOOST_NOEXCEPT : node_() {}
-
- explicit iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
- node_(static_cast<node_pointer>(x)) {}
-
- value_type& operator*() const {
- return node_->value();
- }
-
- value_type* operator->() const {
- return node_->value_ptr();
- }
-
- iterator& operator++() {
- node_ = static_cast<node_pointer>(node_->next_);
- return *this;
- }
-
- iterator operator++(int) {
- iterator tmp(node_);
- node_ = static_cast<node_pointer>(node_->next_);
- return tmp;
- }
-
- bool operator==(iterator const& x) const BOOST_NOEXCEPT {
- return node_ == x.node_;
- }
-
- bool operator!=(iterator const& x) const BOOST_NOEXCEPT {
- return node_ != x.node_;
- }
- };
-
- template <typename Node>
- struct c_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::iterator<Node>;
-
-#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
- typedef typename Node::node_pointer node_pointer;
- typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
- node_pointer node_;
-
- public:
-
- typedef typename Node::value_type value_type;
-
- c_iterator() BOOST_NOEXCEPT : node_() {}
-
- explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
- node_(static_cast<node_pointer>(x)) {}
-
- c_iterator(n_iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {}
-
- value_type const& operator*() const {
- return node_->value();
- }
-
- value_type const* operator->() const {
- return node_->value_ptr();
- }
-
- c_iterator& operator++() {
- node_ = static_cast<node_pointer>(node_->next_);
- return *this;
- }
-
- c_iterator operator++(int) {
- c_iterator tmp(node_);
- node_ = static_cast<node_pointer>(node_->next_);
- return tmp;
- }
-
- friend bool operator==(c_iterator const& x, c_iterator const& y)
- BOOST_NOEXCEPT
- {
- return x.node_ == y.node_;
- }
-
- friend bool operator!=(c_iterator const& x, c_iterator const& y)
- BOOST_NOEXCEPT
- {
- return x.node_ != y.node_;
- }
- };
-}}}
-
-namespace boost { namespace unordered { namespace detail {
-
- ///////////////////////////////////////////////////////////////////
- //
- // Node Holder
- //
- // Temporary store for nodes. Deletes any that aren't used.
-
- template <typename NodeAlloc>
- struct node_holder
- {
- private:
- typedef NodeAlloc node_allocator;
- typedef boost::unordered::detail::allocator_traits<NodeAlloc>
- node_allocator_traits;
- typedef typename node_allocator_traits::value_type node;
- typedef typename node_allocator_traits::pointer node_pointer;
- typedef typename node::value_type value_type;
- typedef typename node::link_pointer link_pointer;
- typedef boost::unordered::iterator_detail::iterator<node> iterator;
-
- node_constructor<NodeAlloc> constructor_;
- node_pointer nodes_;
-
- public:
-
- template <typename Table>
- explicit node_holder(Table& b) :
- constructor_(b.node_alloc()),
- nodes_()
- {
- if (b.size_) {
- typename Table::link_pointer prev = b.get_previous_start();
- nodes_ = static_cast<node_pointer>(prev->next_);
- prev->next_ = link_pointer();
- b.size_ = 0;
- }
- }
-
- ~node_holder();
-
- node_pointer pop_node()
- {
- node_pointer n = nodes_;
- nodes_ = static_cast<node_pointer>(nodes_->next_);
- n->init(n);
- n->next_ = link_pointer();
- return n;
- }
-
- template <typename T>
- inline node_pointer copy_of(T const& v) {
- if (nodes_) {
- constructor_.reclaim(pop_node());
- }
- else {
- constructor_.create_node();
- }
- boost::unordered::detail::func::call_construct(
- constructor_.alloc_, constructor_.node_->value_ptr(), v);
- return constructor_.release();
- }
-
- template <typename T>
- inline node_pointer move_copy_of(T& v) {
- if (nodes_) {
- constructor_.reclaim(pop_node());
- }
- else {
- constructor_.create_node();
- }
- boost::unordered::detail::func::call_construct(
- constructor_.alloc_, constructor_.node_->value_ptr(),
- boost::move(v));
- return constructor_.release();
- }
-
- iterator begin() const
- {
- return iterator(nodes_);
- }
- };
-
- template <typename Alloc>
- node_holder<Alloc>::~node_holder()
- {
- while (nodes_) {
- 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));
- node_allocator_traits::deallocate(constructor_.alloc_, p, 1);
- }
- }
-
- ///////////////////////////////////////////////////////////////////
- //
- // Bucket
-
- template <typename NodePointer>
- struct bucket
- {
- typedef NodePointer link_pointer;
- link_pointer next_;
-
- bucket() : next_() {}
-
- link_pointer first_from_start()
- {
- return next_;
- }
-
- enum { extra_node = true };
- };
-
- struct ptr_bucket
- {
- typedef ptr_bucket* link_pointer;
- link_pointer next_;
-
- ptr_bucket() : next_(0) {}
-
- link_pointer first_from_start()
- {
- return this;
- }
-
- enum { extra_node = false };
- };
-
- ///////////////////////////////////////////////////////////////////
- //
- // Hash Policy
-
- template <typename SizeT>
- struct prime_policy
- {
- template <typename Hash, typename T>
- static inline SizeT apply_hash(Hash const& hf, T const& x) {
- return hf(x);
- }
-
- static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
- return hash % bucket_count;
- }
-
- static inline SizeT new_bucket_count(SizeT min) {
- return boost::unordered::detail::next_prime(min);
- }
-
- static inline SizeT prev_bucket_count(SizeT max) {
- return boost::unordered::detail::prev_prime(max);
- }
- };
-
- template <typename SizeT>
- struct mix64_policy
- {
- template <typename Hash, typename T>
- static inline SizeT apply_hash(Hash const& hf, T const& x) {
- SizeT key = hf(x);
- key = (~key) + (key << 21); // key = (key << 21) - key - 1;
- key = key ^ (key >> 24);
- key = (key + (key << 3)) + (key << 8); // key * 265
- key = key ^ (key >> 14);
- key = (key + (key << 2)) + (key << 4); // key * 21
- key = key ^ (key >> 28);
- key = key + (key << 31);
- return key;
- }
-
- static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
- return hash & (bucket_count - 1);
- }
-
- static inline SizeT new_bucket_count(SizeT min) {
- if (min <= 4) return 4;
- --min;
- min |= min >> 1;
- min |= min >> 2;
- min |= min >> 4;
- min |= min >> 8;
- min |= min >> 16;
- min |= min >> 32;
- return min + 1;
- }
-
- static inline SizeT prev_bucket_count(SizeT max) {
- max |= max >> 1;
- max |= max >> 2;
- max |= max >> 4;
- max |= max >> 8;
- max |= max >> 16;
- max |= max >> 32;
- return (max >> 1) + 1;
- }
- };
-
- template <int digits, int radix>
- struct pick_policy_impl {
- typedef prime_policy<std::size_t> type;
- };
-
- template <>
- struct pick_policy_impl<64, 2> {
- typedef mix64_policy<std::size_t> type;
- };
-
- template <typename T>
- struct pick_policy :
- pick_policy_impl<
- std::numeric_limits<std::size_t>::digits,
- std::numeric_limits<std::size_t>::radix> {};
-
- // While the mix policy is generally faster, the prime policy is a lot
- // faster when a large number consecutive integers are used, because
- // there are no collisions. Since that is probably quite common, use
- // prime policy for integeral types. But not the smaller ones, as they
- // don't have enough unique values for this to be an issue.
-
- template <>
- struct pick_policy<int> {
- typedef prime_policy<std::size_t> type;
- };
-
- template <>
- struct pick_policy<unsigned int> {
- typedef prime_policy<std::size_t> type;
- };
-
- template <>
- struct pick_policy<long> {
- typedef prime_policy<std::size_t> type;
- };
-
- template <>
- struct pick_policy<unsigned long> {
- typedef prime_policy<std::size_t> type;
- };
-
- // TODO: Maybe not if std::size_t is smaller than long long.
-#if !defined(BOOST_NO_LONG_LONG)
- template <>
- struct pick_policy<boost::long_long_type> {
- typedef prime_policy<std::size_t> type;
- };
-
- template <>
- struct pick_policy<boost::ulong_long_type> {
- typedef prime_policy<std::size_t> type;
- };
-#endif
-
- ////////////////////////////////////////////////////////////////////////////
- // Functions
-
- // Assigning and swapping the equality and hash function objects
- // needs strong exception safety. To implement that normally we'd
- // require one of them to be known to not throw and the other to
- // guarantee strong exception safety. Unfortunately they both only
- // have basic exception safety. So to acheive strong exception
- // safety we have storage space for two copies, and assign the new
- // copies to the unused space. Then switch to using that to use
- // them. This is implemented in 'set_hash_functions' which
- // atomically assigns the new function objects in a strongly
- // exception safe manner.
-
- template <class H, class P, bool NoThrowMoveAssign>
- class set_hash_functions;
-
- template <class H, class P>
- class functions
- {
- public:
- static const bool nothrow_move_assignable =
- boost::is_nothrow_move_assignable<H>::value &&
- boost::is_nothrow_move_assignable<P>::value;
- static const bool nothrow_move_constructible =
- boost::is_nothrow_move_constructible<H>::value &&
- boost::is_nothrow_move_constructible<P>::value;
-
- private:
- friend class boost::unordered::detail::set_hash_functions<H, P,
- nothrow_move_assignable>;
- functions& operator=(functions const&);
-
- typedef compressed<H, P> function_pair;
-
- typedef typename boost::aligned_storage<
- sizeof(function_pair),
- boost::alignment_of<function_pair>::value>::type aligned_function;
-
- bool current_; // The currently active functions.
- aligned_function funcs_[2];
-
- function_pair const& current() const {
- return *static_cast<function_pair const*>(
- static_cast<void const*>(&funcs_[current_]));
- }
-
- function_pair& current() {
- return *static_cast<function_pair*>(
- static_cast<void*>(&funcs_[current_]));
- }
-
- void construct(bool which, H const& hf, P const& eq)
- {
- new((void*) &funcs_[which]) function_pair(hf, eq);
- }
-
- void construct(bool which, function_pair const& f,
- boost::unordered::detail::false_type =
- boost::unordered::detail::false_type())
- {
- new((void*) &funcs_[which]) function_pair(f);
- }
-
- void construct(bool which, function_pair& f,
- boost::unordered::detail::true_type)
- {
- new((void*) &funcs_[which]) function_pair(f,
- boost::unordered::detail::move_tag());
- }
-
- void destroy(bool which)
- {
- boost::unordered::detail::func::destroy((function_pair*)(&funcs_[which]));
- }
-
- public:
-
- typedef boost::unordered::detail::set_hash_functions<H, P,
- nothrow_move_assignable> set_hash_functions;
-
- functions(H const& hf, P const& eq)
- : current_(false)
- {
- construct(current_, hf, eq);
- }
-
- functions(functions const& bf)
- : current_(false)
- {
- construct(current_, bf.current());
- }
-
- functions(functions& bf, boost::unordered::detail::move_tag)
- : current_(false)
- {
- construct(current_, bf.current(),
- boost::unordered::detail::integral_constant<bool,
- nothrow_move_constructible>());
- }
-
- ~functions() {
- this->destroy(current_);
- }
-
- H const& hash_function() const {
- return current().first();
- }
-
- P const& key_eq() const {
- return current().second();
- }
- };
-
- template <class H, class P>
- class set_hash_functions<H, P, false>
- {
- set_hash_functions(set_hash_functions const&);
- set_hash_functions& operator=(set_hash_functions const&);
-
- typedef functions<H, P> functions_type;
-
- functions_type& functions_;
- bool tmp_functions_;
-
- public:
-
- set_hash_functions(functions_type& f, H const& h, P const& p)
- : functions_(f),
- tmp_functions_(!f.current_)
- {
- f.construct(tmp_functions_, h, p);
- }
-
- set_hash_functions(functions_type& f, functions_type const& other)
- : functions_(f),
- tmp_functions_(!f.current_)
- {
- f.construct(tmp_functions_, other.current());
- }
-
- ~set_hash_functions()
- {
- functions_.destroy(tmp_functions_);
- }
-
- void commit()
- {
- functions_.current_ = tmp_functions_;
- tmp_functions_ = !tmp_functions_;
- }
- };
-
- template <class H, class P>
- class set_hash_functions<H, P, true>
- {
- set_hash_functions(set_hash_functions const&);
- set_hash_functions& operator=(set_hash_functions const&);
-
- typedef functions<H, P> functions_type;
-
- functions_type& functions_;
- H hash_;
- P pred_;
-
- public:
-
- set_hash_functions(functions_type& f, H const& h, P const& p) :
- functions_(f),
- hash_(h),
- pred_(p) {}
-
- set_hash_functions(functions_type& f, functions_type const& other) :
- functions_(f),
- hash_(other.hash_function()),
- pred_(other.key_eq()) {}
-
- void commit()
- {
- functions_.current().first() = boost::move(hash_);
- functions_.current().second() = boost::move(pred_);
- }
- };
-
- ////////////////////////////////////////////////////////////////////////////
- // rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
- // e.g. for int
-
-#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
-# define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
-#else
- struct please_ignore_this_overload {
- typedef please_ignore_this_overload type;
- };
-
- template <typename T>
- struct rv_ref_impl {
- typedef BOOST_RV_REF(T) type;
- };
-
- template <typename T>
- struct rv_ref :
- boost::detail::if_true<
- boost::is_class<T>::value
- >::BOOST_NESTED_TEMPLATE then <
- boost::unordered::detail::rv_ref_impl<T>,
- please_ignore_this_overload
- >::type
- {};
-
-# define BOOST_UNORDERED_RV_REF(T) \
- typename boost::unordered::detail::rv_ref<T>::type
-#endif
-}}}
-
-#endif
diff --git a/boost/unordered/detail/equivalent.hpp b/boost/unordered/detail/equivalent.hpp
deleted file mode 100644
index 618d3af9b9..0000000000
--- a/boost/unordered/detail/equivalent.hpp
+++ /dev/null
@@ -1,735 +0,0 @@
-
-// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2011 Daniel James
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
-#define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
-
-#include <boost/config.hpp>
-#if defined(BOOST_HAS_PRAGMA_ONCE)
-#pragma once
-#endif
-
-#include <boost/unordered/detail/extract_key.hpp>
-
-namespace boost { namespace unordered { namespace detail {
-
- template <typename A, typename T> struct grouped_node;
- template <typename T> struct grouped_ptr_node;
- template <typename Types> struct grouped_table_impl;
-
- 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;
-
- 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;
-
- 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&);
- };
-
- // 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;
- };
-
- 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::key_type 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;
-
- // 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);
- }
-
- // Node functions.
-
- static inline node_pointer next_node(link_pointer n) {
- return static_cast<node_pointer>(n->next_);
- }
-
- static inline node_pointer next_group(node_pointer n) {
- return static_cast<node_pointer>(n->group_prev_->next_);
- }
-
- // Accessors
-
- template <class Key, class Pred>
- node_pointer find_node_impl(
- std::size_t key_hash,
- Key const& k,
- Pred const& eq) const
- {
- std::size_t bucket_index = this->hash_to_bucket(key_hash);
- node_pointer n = this->begin(bucket_index);
-
- for (;;)
- {
- 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();
- }
-
- n = next_group(n);
- }
- }
-
- std::size_t count(key_type const& k) const
- {
- node_pointer n = this->find_node(k);
- if (!n) return 0;
-
- std::size_t x = 0;
- node_pointer it = n;
- do {
- it = it->group_prev_;
- ++x;
- } while(it != n);
-
- return x;
- }
-
- std::pair<iterator, iterator>
- equal_range(key_type const& k) const
- {
- node_pointer n = this->find_node(k);
- return std::make_pair(iterator(n), iterator(n ? next_group(n) : n));
- }
-
- // Equality
-
- bool equals(grouped_table_impl 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()));
- if (!n2) return false;
- node_pointer end1 = next_group(n1);
- node_pointer end2 = next_group(n2);
- if (!group_equals(n1, end1, n2, end2)) return false;
- n1 = end1;
- }
-
- return true;
- }
-
- static bool group_equals(node_pointer n1, node_pointer end1,
- node_pointer n2, node_pointer end2)
- {
- for(;;)
- {
- if (n1->value() != n2->value()) break;
-
- n1 = next_node(n1);
- n2 = next_node(n2);
-
- if (n1 == end1) return n2 == end2;
- if (n2 == end2) return false;
- }
-
- for(node_pointer n1a = n1, n2a = n2;;)
- {
- n1a = next_node(n1a);
- n2a = next_node(n2a);
-
- if (n1a == end1)
- {
- if (n2a == end2) break;
- else return false;
- }
-
- if (n2a == end2) return false;
- }
-
- node_pointer start = 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 (!matches) return false;
- if (matches != 1 + count_equal(next_node(n1), end1, v)) return false;
- }
- }
-
- return true;
- }
-
- static bool find(node_pointer n, node_pointer end, value_type const& v)
- {
- for(;n != end; n = next_node(n))
- if (n->value() == v)
- return true;
- return false;
- }
-
- static std::size_t count_equal(node_pointer n, node_pointer end,
- value_type const& v)
- {
- std::size_t count = 0;
- for(;n != end; n = next_node(n))
- if (n->value() == v) ++count;
- return count;
- }
-
- // Emplace/Insert
-
- // Add 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'.
- 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;
- }
-
- inline node_pointer add_node(
- node_pointer n,
- std::size_t key_hash,
- node_pointer pos)
- {
- n->hash_ = key_hash;
- if (pos) {
- this->add_to_node_group(n, pos);
- if (n->next_) {
- std::size_t next_bucket = this->hash_to_bucket(
- next_node(n)->hash_);
- if (next_bucket != this->hash_to_bucket(key_hash)) {
- this->get_bucket(next_bucket)->next_ = n;
- }
- }
- }
- else {
- bucket_pointer b = this->get_bucket(
- this->hash_to_bucket(key_hash));
-
- if (!b->next_)
- {
- link_pointer start_node = this->get_previous_start();
-
- if (start_node->next_) {
- this->get_bucket(this->hash_to_bucket(
- next_node(start_node)->hash_
- ))->next_ = n;
- }
-
- b->next_ = start_node;
- n->next_ = start_node->next_;
- start_node->next_ = n;
- }
- else
- {
- n->next_ = b->next_->next_;
- b->next_->next_ = n;
- }
- }
- ++this->size_;
- return n;
- }
-
- inline node_pointer add_using_hint(
- node_pointer n,
- node_pointer hint)
- {
- n->hash_ = hint->hash_;
- this->add_to_node_group(n, hint);
- if (n->next_ != hint && n->next_) {
- std::size_t next_bucket = this->hash_to_bucket(
- next_node(n)->hash_);
- if (next_bucket != this->hash_to_bucket(n->hash_)) {
- this->get_bucket(next_bucket)->next_ = n;
- }
- }
- ++this->size_;
- 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)
- {
- node_tmp a(n, this->node_alloc());
- key_type const& k = this->get_key(a.node_->value());
- 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));
- }
-
- iterator emplace_hint_impl(c_iterator hint, node_pointer n)
- {
- node_tmp a(n, this->node_alloc());
- key_type const& k = this->get_key(a.node_->value());
- if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
- this->reserve_for_insert(this->size_ + 1);
- return iterator(this->add_using_hint(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));
- }
- }
-
- void emplace_impl_no_rehash(node_pointer n)
- {
- node_tmp a(n, this->node_alloc());
- key_type const& k = this->get_key(a.node_->value());
- 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);
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Insert range methods
-
- // if hash function throws, or inserting > 1 element, basic exception
- // safety. Strong otherwise
- template <class I>
- void insert_range(I i, I j, typename
- boost::unordered::detail::enable_if_forward<I, void*>::type = 0)
- {
- if(i == j) return;
-
- std::size_t distance = static_cast<std::size_t>(std::distance(i, j));
- if(distance == 1) {
- emplace_impl(
- 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(
- boost::unordered::detail::func::construct_node(
- this->node_alloc(), *i));
- }
- }
- }
-
- template <class I>
- void insert_range(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(
- this->node_alloc(), *i));
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Erase
- //
- // no throw
-
- std::size_t erase_key(key_type const& 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->get_previous_start(bucket_index);
- if (!prev) return 0;
-
- node_pointer first_node;
-
- for (;;)
- {
- if (!prev->next_) return 0;
- first_node = next_node(prev);
- std::size_t node_hash = first_node->hash_;
- if (this->hash_to_bucket(node_hash) != bucket_index)
- return 0;
- if (node_hash == key_hash &&
- this->key_eq()(k, this->get_key(first_node->value())))
- break;
- prev = first_node->group_prev_;
- }
-
- link_pointer end = first_node->group_prev_->next_;
-
- std::size_t deleted_count = this->delete_nodes(prev, end);
- this->fix_bucket(bucket_index, prev);
- return deleted_count;
- }
-
- iterator erase(c_iterator r)
- {
- BOOST_ASSERT(r.node_);
- node_pointer next = 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_);
- }
-
- 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 = 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 = next_node(prev)->group_prev_;
- }
-
- // Delete the nodes.
- do {
- link_pointer group_end = next_group(next_node(prev));
- this->delete_nodes(prev, group_end);
- bucket_index = this->fix_bucket(bucket_index, prev);
- } while(prev->next_ != j);
-
- return prev;
- }
-
- 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;
- }
-
- ////////////////////////////////////////////////////////////////////////
- // fill_buckets
-
- void copy_buckets(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(next_group(n));
- node_pointer pos = this->add_node(
- 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(
- boost::unordered::detail::func::construct_node(
- this->node_alloc(), n->value()), key_hash, pos);
- }
- }
- }
-
- void move_buckets(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(next_group(n));
- 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 = next_node(n); n != group_end; n = next_node(n))
- {
- this->add_node(
- boost::unordered::detail::func::construct_node(
- this->node_alloc(), boost::move(n->value())), key_hash, pos);
- }
- }
- }
-
- void assign_buckets(table const& src) {
- node_holder<node_allocator> holder(*this);
- for (node_pointer n = src.begin(); n;) {
- std::size_t key_hash = n->hash_;
- node_pointer group_end(next_group(n));
- node_pointer pos = this->add_node(holder.copy_of(n->value()), key_hash, node_pointer());
- for (n = next_node(n); n != group_end; n = next_node(n))
- {
- this->add_node(holder.copy_of(n->value()), key_hash, pos);
- }
- }
- }
-
- void move_assign_buckets(table& src) {
- node_holder<node_allocator> holder(*this);
- for (node_pointer n = src.begin(); n;) {
- std::size_t key_hash = n->hash_;
- node_pointer group_end(next_group(n));
- node_pointer pos = this->add_node(holder.move_copy_of(n->value()), key_hash, node_pointer());
- for (n = next_node(n); n != group_end; n = next_node(n))
- {
- this->add_node(holder.move_copy_of(n->value()), key_hash, pos);
- }
- }
- }
-
- // strong otherwise exception safety
- void 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_)
- prev = place_in_bucket(*this, prev, next_node(prev)->group_prev_);
- }
-
- // Iterate through the nodes placing them in the correct buckets.
- // pre: prev->next_ is not null.
- static link_pointer place_in_bucket(table& dst,
- link_pointer prev, node_pointer end)
- {
- bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(end->hash_));
-
- if (!b->next_) {
- b->next_ = prev;
- return end;
- }
- else {
- link_pointer next = end->next_;
- end->next_ = b->next_->next_;
- b->next_->next_ = prev->next_;
- prev->next_ = next;
- return prev;
- }
- }
- };
-}}}
-
-#endif
diff --git a/boost/unordered/detail/extract_key.hpp b/boost/unordered/detail/extract_key.hpp
deleted file mode 100644
index 338e918ca9..0000000000
--- a/boost/unordered/detail/extract_key.hpp
+++ /dev/null
@@ -1,188 +0,0 @@
-
-// Copyright (C) 2005-2011 Daniel James
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
-#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
-
-#include <boost/config.hpp>
-#if defined(BOOST_HAS_PRAGMA_ONCE)
-#pragma once
-#endif
-
-#include <boost/unordered/detail/table.hpp>
-
-namespace boost {
-namespace unordered {
-namespace detail {
-
- // 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 Key, class ValueType>
- struct map_extractor
- {
- typedef ValueType value_type;
- typedef typename boost::remove_const<Key>::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
- };
-}}}
-
-#endif
diff --git a/boost/unordered/detail/fwd.hpp b/boost/unordered/detail/fwd.hpp
index 7441906234..6a84204200 100644
--- a/boost/unordered/detail/fwd.hpp
+++ b/boost/unordered/detail/fwd.hpp
@@ -15,21 +15,21 @@
// Already defined.
#elif defined(BOOST_LIBSTDCXX11)
// https://github.com/gcc-mirror/gcc/blob/gcc-4_6-branch/libstdc++-v3/include/bits/stl_pair.h#L70
-# if BOOST_LIBSTDCXX_VERSION > 40600
-# define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
-# endif
+#if BOOST_LIBSTDCXX_VERSION > 40600
+#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
+#endif
#elif defined(_LIBCPP_VERSION)
// https://github.com/llvm-mirror/libcxx/blob/release_30/include/utility#L206
-# if LIBCPP_VERSION >= 3000
-# define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
-# endif
+#if LIBCPP_VERSION >= 3000
+#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
+#endif
#elif defined(BOOST_MSVC)
// Apparently C++11 standard supported in Visual Studio 2012
// https://msdn.microsoft.com/en-us/library/hh567368.aspx#stl
// 2012 = VC+11 = BOOST_MSVC 1700 Hopefully!
-# if BOOST_MSVC >= 1700
-# define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
-# endif
+#if BOOST_MSVC >= 1700
+#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
+#endif
#endif
#if !defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
@@ -40,16 +40,16 @@
#include <utility>
#endif
-namespace boost
-{
-namespace unordered
-{
+namespace boost {
+namespace unordered {
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
- using std::piecewise_construct_t;
- using std::piecewise_construct;
+using std::piecewise_construct_t;
+using std::piecewise_construct;
#else
- struct piecewise_construct_t {};
- const piecewise_construct_t piecewise_construct = piecewise_construct_t();
+struct piecewise_construct_t
+{
+};
+const piecewise_construct_t piecewise_construct = piecewise_construct_t();
#endif
}
}
diff --git a/boost/unordered/detail/implementation.hpp b/boost/unordered/detail/implementation.hpp
new file mode 100644
index 0000000000..c293ae2f50
--- /dev/null
+++ b/boost/unordered/detail/implementation.hpp
@@ -0,0 +1,4986 @@
+
+// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
+// Copyright (C) 2005-2016 Daniel James
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNORDERED_DETAIL_IMPLEMENTATION_HPP
+#define BOOST_UNORDERED_DETAIL_IMPLEMENTATION_HPP
+
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/detail/select_type.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+#include <boost/limits.hpp>
+#include <boost/move/move.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/preprocessor/seq/enum.hpp>
+#include <boost/preprocessor/seq/size.hpp>
+#include <boost/swap.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/add_lvalue_reference.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/is_class.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_empty.hpp>
+#include <boost/type_traits/is_nothrow_move_assignable.hpp>
+#include <boost/type_traits/is_nothrow_move_constructible.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/unordered/detail/fwd.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <cmath>
+#include <iterator>
+#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
+
+////////////////////////////////////////////////////////////////////////////////
+// Configuration
+//
+// 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.
+
+#if !defined BOOST_UNORDERED_EMPLACE_LIMIT
+#define BOOST_UNORDERED_EMPLACE_LIMIT 11
+#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.
+
+#if !defined(BOOST_UNORDERED_INTEROPERABLE_NODES)
+#define BOOST_UNORDERED_INTEROPERABLE_NODES 0
+#endif
+
+// BOOST_UNORDERED_USE_ALLOCATOR_TRAITS - Pick which version of
+// allocator_traits to use.
+//
+// 0 = Own partial implementation
+// 1 = std::allocator_traits
+// 2 = boost::container::allocator_traits
+
+#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+#define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
+#elif defined(BOOST_MSVC)
+#if BOOST_MSVC < 1400
+// Use container's allocator_traits for older versions of Visual
+// C++ as I don't test with them.
+#define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
+#endif
+#endif
+#endif
+
+#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
+#define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
+#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;
+}
+}
+}
+
+namespace boost {
+namespace unordered {
+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 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
+{
+};
+
+namespace func {
+template <class T> inline void ignore_unused_variable_warning(T const&) {}
+}
+
+////////////////////////////////////////////////////////////////////////////
+// iterator SFINAE
+
+template <typename I>
+struct is_forward
+ : boost::is_convertible<typename boost::iterator_traversal<I>::type,
+ boost::forward_traversal_tag>
+{
+};
+
+template <typename I, typename ReturnType>
+struct enable_if_forward
+ : boost::enable_if_c<boost::unordered::detail::is_forward<I>::value,
+ ReturnType>
+{
+};
+
+template <typename I, typename ReturnType>
+struct disable_if_forward
+ : boost::disable_if_c<boost::unordered::detail::is_forward<I>::value,
+ ReturnType>
+{
+};
+
+////////////////////////////////////////////////////////////////////////////
+// primes
+
+// clang-format off
+#define BOOST_UNORDERED_PRIMES \
+ (17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
+ (97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \
+ (1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \
+ (49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \
+ (1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul) \
+ (50331653ul)(100663319ul)(201326611ul)(402653189ul)(805306457ul) \
+ (1610612741ul)(3221225473ul)(4294967291ul)
+// clang-format on
+
+template <class T> struct prime_list_template
+{
+ static std::size_t const value[];
+
+#if !defined(SUNPRO_CC)
+ static std::ptrdiff_t const length;
+#else
+ static std::ptrdiff_t const length =
+ BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
+#endif
+};
+
+template <class T>
+std::size_t const prime_list_template<T>::value[] = {
+ BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIMES)};
+
+#if !defined(SUNPRO_CC)
+template <class T>
+std::ptrdiff_t const prime_list_template<T>::length = BOOST_PP_SEQ_SIZE(
+ BOOST_UNORDERED_PRIMES);
+#endif
+
+#undef BOOST_UNORDERED_PRIMES
+
+typedef prime_list_template<std::size_t> prime_list;
+
+// no throw
+inline std::size_t next_prime(std::size_t num)
+{
+ std::size_t const* const prime_list_begin = prime_list::value;
+ std::size_t const* const prime_list_end =
+ prime_list_begin + prime_list::length;
+ std::size_t const* bound =
+ std::lower_bound(prime_list_begin, prime_list_end, num);
+ if (bound == prime_list_end)
+ bound--;
+ return *bound;
+}
+
+// no throw
+inline std::size_t prev_prime(std::size_t num)
+{
+ std::size_t const* const prime_list_begin = prime_list::value;
+ std::size_t const* const prime_list_end =
+ prime_list_begin + prime_list::length;
+ std::size_t const* bound =
+ std::upper_bound(prime_list_begin, prime_list_end, num);
+ if (bound != prime_list_begin)
+ bound--;
+ return *bound;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// insert_size/initial_size
+
+template <class I>
+inline std::size_t insert_size(I i, I j,
+ typename boost::unordered::detail::enable_if_forward<I, void*>::type = 0)
+{
+ return static_cast<std::size_t>(std::distance(i, j));
+}
+
+template <class I>
+inline std::size_t insert_size(I, I,
+ typename boost::unordered::detail::disable_if_forward<I, void*>::type = 0)
+{
+ return 1;
+}
+
+template <class I>
+inline std::size_t initial_size(I i, I j,
+ std::size_t num_buckets = boost::unordered::detail::default_bucket_count)
+{
+ // TODO: Why +1?
+ return (std::max)(
+ boost::unordered::detail::insert_size(i, j) + 1, num_buckets);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// compressed
+
+template <typename T, int Index> struct compressed_base : private T
+{
+ compressed_base(T const& x) : T(x) {}
+ compressed_base(T& x, move_tag) : T(boost::move(x)) {}
+
+ T& get() { return *this; }
+ T const& get() const { return *this; }
+};
+
+template <typename T, int Index> struct uncompressed_base
+{
+ uncompressed_base(T const& x) : value_(x) {}
+ uncompressed_base(T& x, move_tag) : value_(boost::move(x)) {}
+
+ T& get() { return value_; }
+ T const& get() const { return value_; }
+ private:
+ T value_;
+};
+
+template <typename T, int Index>
+struct generate_base
+ : boost::detail::if_true<boost::is_empty<T>::value>::BOOST_NESTED_TEMPLATE
+ then<boost::unordered::detail::compressed_base<T, Index>,
+ boost::unordered::detail::uncompressed_base<T, Index> >
+{
+};
+
+template <typename T1, typename T2>
+struct compressed
+ : private boost::unordered::detail::generate_base<T1, 1>::type,
+ private boost::unordered::detail::generate_base<T2, 2>::type
+{
+ typedef typename generate_base<T1, 1>::type base1;
+ typedef typename generate_base<T2, 2>::type base2;
+
+ typedef T1 first_type;
+ typedef T2 second_type;
+
+ first_type& first() { return static_cast<base1*>(this)->get(); }
+
+ first_type const& first() const
+ {
+ return static_cast<base1 const*>(this)->get();
+ }
+
+ second_type& second() { return static_cast<base2*>(this)->get(); }
+
+ second_type const& second() const
+ {
+ return static_cast<base2 const*>(this)->get();
+ }
+
+ template <typename First, typename Second>
+ compressed(First const& x1, Second const& x2) : base1(x1), base2(x2)
+ {
+ }
+
+ compressed(compressed const& x) : base1(x.first()), base2(x.second()) {}
+
+ compressed(compressed& x, move_tag m)
+ : base1(x.first(), m), base2(x.second(), m)
+ {
+ }
+
+ void assign(compressed const& x)
+ {
+ first() = x.first();
+ second() = x.second();
+ }
+
+ void move_assign(compressed& x)
+ {
+ first() = boost::move(x.first());
+ second() = boost::move(x.second());
+ }
+
+ void swap(compressed& x)
+ {
+ boost::swap(first(), x.first());
+ boost::swap(second(), x.second());
+ }
+
+ private:
+ // Prevent assignment just to make use of assign or
+ // move_assign explicit.
+ compressed& operator=(compressed const&);
+};
+
+////////////////////////////////////////////////////////////////////////////
+// pair_traits
+//
+// Used to get the types from a pair without instantiating it.
+
+template <typename Pair> struct pair_traits
+{
+ typedef typename Pair::first_type first_type;
+ typedef typename Pair::second_type second_type;
+};
+
+template <typename T1, typename T2> struct pair_traits<std::pair<T1, T2> >
+{
+ typedef T1 first_type;
+ typedef T2 second_type;
+};
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable : 4512) // assignment operator could not be generated.
+#pragma warning(disable : 4345) // behavior change: an object of POD type
+// constructed with an initializer of the form ()
+// will be default-initialized.
+#endif
+
+////////////////////////////////////////////////////////////////////////////
+// Bits and pieces for implementing traits
+
+template <typename T> typename boost::add_lvalue_reference<T>::type make();
+struct choice9
+{
+ typedef char (&type)[9];
+};
+struct choice8 : choice9
+{
+ typedef char (&type)[8];
+};
+struct choice7 : choice8
+{
+ typedef char (&type)[7];
+};
+struct choice6 : choice7
+{
+ typedef char (&type)[6];
+};
+struct choice5 : choice6
+{
+ typedef char (&type)[5];
+};
+struct choice4 : choice5
+{
+ typedef char (&type)[4];
+};
+struct choice3 : choice4
+{
+ typedef char (&type)[3];
+};
+struct choice2 : choice3
+{
+ typedef char (&type)[2];
+};
+struct choice1 : choice2
+{
+ typedef char (&type)[1];
+};
+choice1 choose();
+
+typedef choice1::type yes_type;
+typedef choice2::type no_type;
+
+struct private_type
+{
+ private_type const& operator,(int) const;
+};
+
+template <typename T> no_type is_private_type(T const&);
+yes_type is_private_type(private_type const&);
+
+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)
+{
+ return const_cast<T*>(x);
+}
+}
+
+////////////////////////////////////////////////////////////////////////////
+// emplace_args
+//
+// Either forwarding variadic arguments, or storing the arguments in
+// emplace_args##n
+
+#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
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
+ typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \
+ BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
+
+#else
+
+#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
+ typedef typename boost::add_lvalue_reference<BOOST_PP_CAT(A, n)>::type \
+ BOOST_PP_CAT(Arg, n); \
+ BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
+
+#endif
+
+template <typename A0> struct emplace_args1
+{
+ BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
+
+ explicit emplace_args1(Arg0 b0) : a0(b0) {}
+};
+
+template <typename A0>
+inline emplace_args1<A0> create_emplace_args(BOOST_FWD_REF(A0) b0)
+{
+ emplace_args1<A0> e(b0);
+ return e;
+}
+
+template <typename A0, typename A1> struct emplace_args2
+{
+ BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
+ BOOST_UNORDERED_EARGS_MEMBER(1, 1, _)
+
+ emplace_args2(Arg0 b0, Arg1 b1) : a0(b0), a1(b1) {}
+};
+
+template <typename A0, typename A1>
+inline emplace_args2<A0, A1> create_emplace_args(
+ BOOST_FWD_REF(A0) b0, BOOST_FWD_REF(A1) b1)
+{
+ emplace_args2<A0, A1> e(b0, b1);
+ return e;
+}
+
+template <typename A0, typename A1, typename A2> struct emplace_args3
+{
+ BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
+ BOOST_UNORDERED_EARGS_MEMBER(1, 1, _)
+ BOOST_UNORDERED_EARGS_MEMBER(1, 2, _)
+
+ emplace_args3(Arg0 b0, Arg1 b1, Arg2 b2) : a0(b0), a1(b1), a2(b2) {}
+};
+
+template <typename A0, typename A1, typename A2>
+inline emplace_args3<A0, A1, A2> create_emplace_args(
+ BOOST_FWD_REF(A0) b0, BOOST_FWD_REF(A1) b1, BOOST_FWD_REF(A2) b2)
+{
+ emplace_args3<A0, A1, A2> e(b0, b1, b2);
+ return e;
+}
+
+#define BOOST_UNORDERED_FWD_PARAM(z, n, a) \
+ BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n)
+
+#define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \
+ boost::forward<BOOST_PP_CAT(A, i)>(BOOST_PP_CAT(a, i))
+
+#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
+ BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
+
+#define BOOST_UNORDERED_EARGS(z, n, _) \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
+ struct BOOST_PP_CAT(emplace_args, n) \
+ { \
+ BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) BOOST_PP_CAT( \
+ emplace_args, n)(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, b)) \
+ : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \
+ { \
+ } \
+ }; \
+ \
+ template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
+ inline BOOST_PP_CAT(emplace_args, n)<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> \
+ create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, b)) \
+ { \
+ BOOST_PP_CAT(emplace_args, n)<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> e( \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, b)); \
+ return e; \
+ }
+
+BOOST_PP_REPEAT_FROM_TO(
+ 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS, _)
+
+#undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS
+#undef BOOST_UNORDERED_EARGS_MEMBER
+#undef BOOST_UNORDERED_EARGS_INIT
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Some utilities for implementing allocator_traits, but useful elsewhere so
+// they're always defined.
+
+////////////////////////////////////////////////////////////////////////////
+// Integral_constrant, true_type, false_type
+//
+// Uses the standard versions if available.
+
+#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
+
+using std::integral_constant;
+using std::true_type;
+using std::false_type;
+
+#else
+
+template <typename T, T Value> struct integral_constant
+{
+ enum
+ {
+ value = Value
+ };
+};
+
+typedef boost::unordered::detail::integral_constant<bool, true> true_type;
+typedef boost::unordered::detail::integral_constant<bool, false> false_type;
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////
+// Explicitly call a destructor
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable : 4100) // unreferenced formal parameter
+#endif
+
+namespace func {
+template <class T> inline void destroy(T* x) { x->~T(); }
+}
+
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
+////////////////////////////////////////////////////////////////////////////
+// Expression test mechanism
+//
+// When SFINAE expressions are available, define
+// BOOST_UNORDERED_HAS_FUNCTION which can check if a function call is
+// supported by a class, otherwise define BOOST_UNORDERED_HAS_MEMBER which
+// can detect if a class has the specified member, but not that it has the
+// correct type, this is good enough for a passable impression of
+// allocator_traits.
+
+#if !defined(BOOST_NO_SFINAE_EXPR)
+
+template <typename T, long unsigned int> struct expr_test;
+template <typename T> struct expr_test<T, sizeof(char)> : T
+{
+};
+
+#define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
+ template <typename U> \
+ static typename boost::unordered::detail::expr_test<BOOST_PP_CAT( \
+ choice, result), \
+ sizeof(for_expr_test(((expression), 0)))>::type \
+ test(BOOST_PP_CAT(choice, count))
+
+#define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
+ template <typename U> \
+ static BOOST_PP_CAT(choice, result)::type test( \
+ BOOST_PP_CAT(choice, count))
+
+#define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
+ struct BOOST_PP_CAT(has_, name) \
+ { \
+ template <typename U> static char for_expr_test(U const&); \
+ BOOST_UNORDERED_CHECK_EXPRESSION( \
+ 1, 1, boost::unordered::detail::make<thing>().name args); \
+ BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
+ \
+ enum \
+ { \
+ value = sizeof(test<T>(choose())) == sizeof(choice1::type) \
+ }; \
+ }
+
+#else
+
+template <typename T> struct identity
+{
+ typedef T type;
+};
+
+#define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
+ \
+ typedef typename boost::unordered::detail::identity<member>::type \
+ BOOST_PP_CAT(check, count); \
+ \
+ template <BOOST_PP_CAT(check, count) e> struct BOOST_PP_CAT(test, count) \
+ { \
+ typedef BOOST_PP_CAT(choice, result) type; \
+ }; \
+ \
+ template <class U> \
+ static typename BOOST_PP_CAT(test, count)<&U::name>::type test( \
+ BOOST_PP_CAT(choice, count))
+
+#define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
+ template <class U> \
+ static BOOST_PP_CAT(choice, result)::type test( \
+ BOOST_PP_CAT(choice, count))
+
+#define BOOST_UNORDERED_HAS_MEMBER(name) \
+ struct BOOST_PP_CAT(has_, name) \
+ { \
+ struct impl \
+ { \
+ struct base_mixin \
+ { \
+ int name; \
+ }; \
+ struct base : public T, public base_mixin \
+ { \
+ }; \
+ \
+ BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \
+ BOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \
+ \
+ enum \
+ { \
+ value = sizeof(choice2::type) == sizeof(test<base>(choose())) \
+ }; \
+ }; \
+ \
+ enum \
+ { \
+ value = impl::value \
+ }; \
+ }
+
+#endif
+}
+}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Allocator traits
+//
+// First our implementation, then later light wrappers around the alternatives
+
+#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
+
+#include <boost/limits.hpp>
+#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 {
+
+template <typename Alloc, typename T> struct rebind_alloc;
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template <template <typename, typename...> class Alloc, typename U, typename T,
+ typename... Args>
+struct rebind_alloc<Alloc<U, Args...>, T>
+{
+ typedef Alloc<T, Args...> type;
+};
+
+#else
+
+template <template <typename> class Alloc, typename U, typename T>
+struct rebind_alloc<Alloc<U>, T>
+{
+ typedef Alloc<T> type;
+};
+
+template <template <typename, typename> class Alloc, typename U, typename T,
+ typename A0>
+struct rebind_alloc<Alloc<U, A0>, T>
+{
+ typedef Alloc<T, A0> type;
+};
+
+template <template <typename, typename, typename> class Alloc, typename U,
+ typename T, typename A0, typename A1>
+struct rebind_alloc<Alloc<U, A0, A1>, T>
+{
+ typedef Alloc<T, A0, A1> type;
+};
+
+#endif
+
+template <typename Alloc, typename T> struct rebind_wrap
+{
+ template <typename X>
+ static choice1::type test(
+ choice1, typename X::BOOST_NESTED_TEMPLATE rebind<T>::other* = 0);
+ template <typename X> static choice2::type test(choice2, void* = 0);
+
+ enum
+ {
+ value = (1 == sizeof(test<Alloc>(choose())))
+ };
+
+ struct fallback
+ {
+ template <typename U> struct rebind
+ {
+ typedef typename rebind_alloc<Alloc, T>::type other;
+ };
+ };
+
+ typedef typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE then<
+ Alloc, fallback>::type::BOOST_NESTED_TEMPLATE rebind<T>::other type;
+};
+
+#if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
+
+#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
+ template <typename Tp, typename Default> struct default_type_##tname \
+ { \
+ \
+ template <typename X> \
+ static choice1::type test(choice1, typename X::tname* = 0); \
+ \
+ template <typename X> static choice2::type test(choice2, void* = 0); \
+ \
+ struct DefaultWrap \
+ { \
+ typedef Default tname; \
+ }; \
+ \
+ enum \
+ { \
+ value = (1 == sizeof(test<Tp>(choose()))) \
+ }; \
+ \
+ typedef typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE \
+ then<Tp, DefaultWrap>::type::tname type; \
+ }
+
+#else
+
+template <typename T, typename T2> struct sfinae : T2
+{
+};
+
+#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
+ template <typename Tp, typename Default> struct default_type_##tname \
+ { \
+ \
+ template <typename X> \
+ static typename boost::unordered::detail::sfinae<typename X::tname, \
+ choice1>::type test(choice1); \
+ \
+ template <typename X> static choice2::type test(choice2); \
+ \
+ struct DefaultWrap \
+ { \
+ typedef Default tname; \
+ }; \
+ \
+ enum \
+ { \
+ value = (1 == sizeof(test<Tp>(choose()))) \
+ }; \
+ \
+ typedef typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE \
+ then<Tp, DefaultWrap>::type::tname type; \
+ }
+
+#endif
+
+#define BOOST_UNORDERED_DEFAULT_TYPE(T, tname, arg) \
+ typename default_type_##tname<T, arg>::type
+
+BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
+BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
+BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer);
+BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer);
+BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type);
+BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type);
+BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
+BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
+BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
+
+#if !defined(BOOST_NO_SFINAE_EXPR)
+
+template <typename T>
+BOOST_UNORDERED_HAS_FUNCTION(
+ select_on_container_copy_construction, U const, (), 0);
+
+template <typename T> BOOST_UNORDERED_HAS_FUNCTION(max_size, U const, (), 0);
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template <typename T, typename ValueType, typename... Args>
+BOOST_UNORDERED_HAS_FUNCTION(
+ construct, U, (boost::unordered::detail::make<ValueType*>(),
+ boost::unordered::detail::make<Args const>()...),
+ 2);
+
+#else
+
+template <typename T, typename ValueType>
+BOOST_UNORDERED_HAS_FUNCTION(
+ construct, U, (boost::unordered::detail::make<ValueType*>(),
+ boost::unordered::detail::make<ValueType const>()),
+ 2);
+
+#endif
+
+template <typename T, typename ValueType>
+BOOST_UNORDERED_HAS_FUNCTION(
+ destroy, U, (boost::unordered::detail::make<ValueType*>()), 1);
+
+#else
+
+template <typename T>
+BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
+
+template <typename T> BOOST_UNORDERED_HAS_MEMBER(max_size);
+
+template <typename T, typename ValueType> BOOST_UNORDERED_HAS_MEMBER(construct);
+
+template <typename T, typename ValueType> BOOST_UNORDERED_HAS_MEMBER(destroy);
+
+#endif
+
+namespace func {
+
+template <typename Alloc>
+inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
+ typename boost::enable_if_c<
+ boost::unordered::detail::has_select_on_container_copy_construction<
+ Alloc>::value,
+ void*>::type = 0)
+{
+ return rhs.select_on_container_copy_construction();
+}
+
+template <typename Alloc>
+inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
+ typename boost::disable_if_c<
+ boost::unordered::detail::has_select_on_container_copy_construction<
+ Alloc>::value,
+ void*>::type = 0)
+{
+ return rhs;
+}
+
+template <typename SizeType, typename Alloc>
+inline SizeType call_max_size(const Alloc& a,
+ typename boost::enable_if_c<
+ boost::unordered::detail::has_max_size<Alloc>::value, void*>::type = 0)
+{
+ return a.max_size();
+}
+
+template <typename SizeType, typename Alloc>
+inline SizeType call_max_size(const Alloc&,
+ typename boost::disable_if_c<
+ boost::unordered::detail::has_max_size<Alloc>::value, void*>::type = 0)
+{
+ return (std::numeric_limits<SizeType>::max)();
+}
+
+} // namespace func.
+
+template <typename Alloc> struct allocator_traits
+{
+ typedef Alloc allocator_type;
+ typedef typename Alloc::value_type value_type;
+
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*) pointer;
+
+ template <typename T>
+ struct pointer_to_other : boost::pointer_to_other<pointer, T>
+ {
+ };
+
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
+ typename pointer_to_other<const value_type>::type) const_pointer;
+
+ // typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
+ // typename pointer_to_other<void>::type)
+ // void_pointer;
+ //
+ // typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
+ // typename pointer_to_other<const void>::type)
+ // const_void_pointer;
+
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(
+ Alloc, difference_type, std::ptrdiff_t) difference_type;
+
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(
+ Alloc, size_type, std::size_t) size_type;
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ template <typename T>
+ using rebind_alloc = typename rebind_wrap<Alloc, T>::type;
+
+ template <typename T>
+ using rebind_traits =
+ boost::unordered::detail::allocator_traits<rebind_alloc<T> >;
+#endif
+
+ static pointer allocate(Alloc& a, size_type n) { return a.allocate(n); }
+
+ // I never use this, so I'll just comment it out for now.
+ //
+ // static pointer allocate(Alloc& a, size_type n,
+ // const_void_pointer hint)
+ // { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
+
+ static void deallocate(Alloc& a, pointer p, size_type n)
+ {
+ a.deallocate(p, n);
+ }
+
+ public:
+#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+
+ template <typename T, typename... Args>
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_construct<Alloc, T, Args...>::value>::type
+ construct(Alloc& a, T* p, BOOST_FWD_REF(Args)... x)
+ {
+ a.construct(p, boost::forward<Args>(x)...);
+ }
+
+ template <typename T, typename... Args>
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_construct<Alloc, T, Args...>::value>::type
+ construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x)
+ {
+ new (static_cast<void*>(p)) T(boost::forward<Args>(x)...);
+ }
+
+ template <typename T>
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_destroy<Alloc, T>::value>::type
+ destroy(Alloc& a, T* p)
+ {
+ a.destroy(p);
+ }
+
+ template <typename T>
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_destroy<Alloc, T>::value>::type
+ destroy(Alloc&, T* p)
+ {
+ boost::unordered::detail::func::destroy(p);
+ }
+
+#elif !defined(BOOST_NO_SFINAE_EXPR)
+
+ template <typename T>
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_construct<Alloc, T>::value>::type
+ construct(Alloc& a, T* p, T const& x)
+ {
+ a.construct(p, x);
+ }
+
+ template <typename T>
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_construct<Alloc, T>::value>::type
+ construct(Alloc&, T* p, T const& x)
+ {
+ new (static_cast<void*>(p)) T(x);
+ }
+
+ template <typename T>
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_destroy<Alloc, T>::value>::type
+ destroy(Alloc& a, T* p)
+ {
+ a.destroy(p);
+ }
+
+ template <typename T>
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_destroy<Alloc, T>::value>::type
+ destroy(Alloc&, T* p)
+ {
+ boost::unordered::detail::func::destroy(p);
+ }
+
+#else
+
+ // If we don't have SFINAE expressions, only call construct for the
+ // copy constructor for the allocator's value_type - as that's
+ // the only construct method that old fashioned allocators support.
+
+ template <typename T>
+ static void construct(Alloc& a, T* p, T const& x,
+ typename boost::enable_if_c<
+ boost::unordered::detail::has_construct<Alloc, T>::value &&
+ boost::is_same<T, value_type>::value,
+ void*>::type = 0)
+ {
+ a.construct(p, x);
+ }
+
+ template <typename T>
+ static void construct(Alloc&, T* p, T const& x,
+ typename boost::disable_if_c<
+ boost::unordered::detail::has_construct<Alloc, T>::value &&
+ boost::is_same<T, value_type>::value,
+ void*>::type = 0)
+ {
+ new (static_cast<void*>(p)) T(x);
+ }
+
+ template <typename T>
+ static void destroy(Alloc& a, T* p,
+ typename boost::enable_if_c<
+ boost::unordered::detail::has_destroy<Alloc, T>::value &&
+ boost::is_same<T, value_type>::value,
+ void*>::type = 0)
+ {
+ a.destroy(p);
+ }
+
+ template <typename T>
+ static void destroy(Alloc&, T* p,
+ typename boost::disable_if_c<
+ boost::unordered::detail::has_destroy<Alloc, T>::value &&
+ boost::is_same<T, value_type>::value,
+ void*>::type = 0)
+ {
+ boost::unordered::detail::func::destroy(p);
+ }
+
+#endif
+
+ static size_type max_size(const Alloc& a)
+ {
+ return boost::unordered::detail::func::call_max_size<size_type>(a);
+ }
+
+ // Allocator propagation on construction
+
+ static Alloc select_on_container_copy_construction(Alloc const& rhs)
+ {
+ return boost::unordered::detail::func::
+ call_select_on_container_copy_construction(rhs);
+ }
+
+ // Allocator propagation on assignment and swap.
+ // Return true if lhs is modified.
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc,
+ propagate_on_container_copy_assignment,
+ false_type) propagate_on_container_copy_assignment;
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc,
+ propagate_on_container_move_assignment,
+ false_type) propagate_on_container_move_assignment;
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, propagate_on_container_swap,
+ false_type) propagate_on_container_swap;
+};
+}
+}
+}
+
+#undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
+#undef BOOST_UNORDERED_DEFAULT_TYPE
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// std::allocator_traits
+
+#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
+
+#include <memory>
+
+#define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
+
+namespace boost {
+namespace unordered {
+namespace detail {
+
+template <typename Alloc> struct allocator_traits : std::allocator_traits<Alloc>
+{
+};
+
+template <typename Alloc, typename T> struct rebind_wrap
+{
+ typedef typename std::allocator_traits<Alloc>::template rebind_alloc<T>
+ type;
+};
+}
+}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// boost::container::allocator_traits
+
+#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
+
+#include <boost/container/allocator_traits.hpp>
+
+#define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
+
+namespace boost {
+namespace unordered {
+namespace detail {
+
+template <typename Alloc>
+struct allocator_traits : boost::container::allocator_traits<Alloc>
+{
+};
+
+template <typename Alloc, typename T>
+struct rebind_wrap : boost::container::allocator_traits<
+ Alloc>::template portable_rebind_alloc<T>
+{
+};
+}
+}
+}
+
+#else
+
+#error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////
+// Functions used to construct nodes. Emulates variadic construction,
+// piecewise construction etc.
+
+namespace boost {
+namespace unordered {
+namespace detail {
+namespace func {
+
+////////////////////////////////////////////////////////////////////////////
+// call_construct
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+
+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
+
+template <typename Alloc, typename T, typename... Args>
+inline void call_construct(Alloc&, 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
+
+#else
+template <typename Alloc, typename T>
+inline void call_construct(Alloc&, 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)
+{
+ 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);
+}
+
+#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_)
+
+#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& alloc, T* ptr, \
+ namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
+ { \
+ boost::unordered::detail::func::call_construct(alloc, ptr, \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_)); \
+ }
+
+#define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) namespace_ get<n>(x)
+
+#elif !defined(__SUNPRO_CC)
+
+#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_)
+
+#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_)); \
+ }
+
+#define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) namespace_ get<n>(x)
+
+#else
+
+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_) \
+ 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) \
+ { \
+ 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
+
+#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
+#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
+#undef BOOST_UNORDERED_GET_TUPLE_ARG
+
+#if defined(__SUNPRO_CC)
+
+template <typename Alloc, typename T, typename Tuple>
+void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
+{
+ construct_from_tuple_impl(boost::unordered::detail::func::length<
+ boost::tuples::length<Tuple>::value>(),
+ alloc, ptr, x);
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////
+// Trait to check for piecewise construction.
+
+template <typename A0> struct use_piecewise
+{
+ static choice1::type test(choice1, boost::unordered::piecewise_construct_t);
+
+ static choice2::type test(choice2, ...);
+
+ enum
+ {
+ value = sizeof(choice1::type) ==
+ sizeof(test(choose(), boost::unordered::detail::make<A0>()))
+ };
+};
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+////////////////////////////////////////////////////////////////////////////
+// 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(
+ 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.
+
+template <typename Alloc, typename A, typename B, typename A0, typename A1,
+ typename A2>
+inline typename enable_if<use_piecewise<A0>, 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::unordered::detail::func::const_cast_pointer(
+ 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));
+ }
+ BOOST_CATCH(...)
+ {
+ boost::unordered::detail::func::call_destroy(
+ alloc, boost::unordered::detail::func::const_cast_pointer(
+ boost::addressof(address->first)));
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+}
+
+#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+////////////////////////////////////////////////////////////////////////////
+// Construct from emplace_args
+
+// Explicitly write out first three overloads for the sake of sane
+// error messages.
+
+template <typename Alloc, typename T, typename A0>
+inline void construct_from_args(
+ Alloc&, T* address, emplace_args1<A0> const& args)
+{
+ new ((void*)address) T(boost::forward<A0>(args.a0));
+}
+
+template <typename Alloc, typename T, typename A0, typename A1>
+inline void construct_from_args(
+ Alloc&, T* address, emplace_args2<A0, A1> const& args)
+{
+ new ((void*)address)
+ T(boost::forward<A0>(args.a0), boost::forward<A1>(args.a1));
+}
+
+template <typename Alloc, typename T, typename A0, typename A1, typename A2>
+inline void construct_from_args(
+ Alloc&, T* address, emplace_args3<A0, A1, A2> const& args)
+{
+ new ((void*)address) T(boost::forward<A0>(args.a0),
+ boost::forward<A1>(args.a1), boost::forward<A2>(args.a2));
+}
+
+// Use a macro for the rest.
+
+#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
+ template <typename Alloc, typename T, \
+ BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A)> \
+ inline void construct_from_args(Alloc&, T* address, \
+ boost::unordered::detail::BOOST_PP_CAT(emplace_args, num_params) < \
+ BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) > const& args) \
+ { \
+ new ((void*)address) T(BOOST_PP_ENUM_##z( \
+ num_params, BOOST_UNORDERED_CALL_FORWARD, args.a)); \
+ }
+
+BOOST_PP_REPEAT_FROM_TO(
+ 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_CONSTRUCT_IMPL, _)
+
+#undef BOOST_UNORDERED_CONSTRUCT_IMPL
+
+// Construct with piece_construct
+
+template <typename Alloc, typename A, typename B, typename A0, typename A1,
+ typename A2>
+inline void construct_from_args(Alloc& alloc, std::pair<A, B>* address,
+ boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
+ 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);
+ BOOST_TRY
+ {
+ boost::unordered::detail::func::construct_from_tuple(
+ alloc, boost::unordered::detail::func::const_cast_pointer(
+ 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_CATCH_END
+}
+
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+}
+}
+}
+}
+
+namespace boost {
+namespace unordered {
+namespace detail {
+
+///////////////////////////////////////////////////////////////////
+//
+// Node construction
+
+template <typename NodeAlloc> struct node_constructor
+{
+ typedef NodeAlloc node_allocator;
+ typedef boost::unordered::detail::allocator_traits<NodeAlloc>
+ node_allocator_traits;
+ typedef typename node_allocator_traits::value_type node;
+ typedef typename node_allocator_traits::pointer node_pointer;
+ typedef typename node::value_type value_type;
+
+ node_allocator& alloc_;
+ node_pointer node_;
+ bool node_constructed_;
+
+ node_constructor(node_allocator& n)
+ : alloc_(n), node_(), node_constructed_(false)
+ {
+ }
+
+ ~node_constructor();
+
+ void create_node();
+
+ // no throw
+ node_pointer release()
+ {
+ BOOST_ASSERT(node_ && node_constructed_);
+ node_pointer p = node_;
+ node_ = node_pointer();
+ return p;
+ }
+
+ void reclaim(node_pointer p)
+ {
+ BOOST_ASSERT(!node_);
+ node_ = p;
+ node_constructed_ = true;
+ boost::unordered::detail::func::call_destroy(
+ alloc_, node_->value_ptr());
+ }
+
+ private:
+ node_constructor(node_constructor const&);
+ node_constructor& operator=(node_constructor const&);
+};
+
+template <typename Alloc> node_constructor<Alloc>::~node_constructor()
+{
+ if (node_) {
+ if (node_constructed_) {
+ boost::unordered::detail::func::destroy(boost::addressof(*node_));
+ }
+
+ node_allocator_traits::deallocate(alloc_, node_, 1);
+ }
+}
+
+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;
+}
+
+template <typename NodeAlloc> struct node_tmp
+{
+ typedef boost::unordered::detail::allocator_traits<NodeAlloc>
+ node_allocator_traits;
+ typedef typename node_allocator_traits::pointer node_pointer;
+
+ NodeAlloc& alloc_;
+ node_pointer node_;
+
+ explicit node_tmp(node_pointer n, NodeAlloc& a) : alloc_(a), node_(n) {}
+
+ ~node_tmp();
+
+ // no throw
+ node_pointer release()
+ {
+ node_pointer p = node_;
+ node_ = node_pointer();
+ return p;
+ }
+};
+
+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_));
+ node_allocator_traits::deallocate(alloc_, node_, 1);
+ }
+}
+}
+}
+}
+
+namespace boost {
+namespace unordered {
+namespace detail {
+namespace func {
+
+// Some nicer construct_node functions, might try to
+// improve implementation later.
+
+template <typename Alloc, BOOST_UNORDERED_EMPLACE_TEMPLATE>
+inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
+construct_node_from_args(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS)
+{
+ node_constructor<Alloc> a(alloc);
+ a.create_node();
+ construct_from_args(
+ alloc, a.node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ return a.release();
+}
+
+template <typename Alloc, typename U>
+inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
+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));
+ return a.release();
+}
+
+// TODO: When possible, it might be better to use std::pair's
+// constructor for std::piece_construct with std::tuple.
+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_TRY
+ {
+ boost::unordered::detail::func::call_construct(
+ alloc, boost::unordered::detail::func::const_cast_pointer(
+ 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_CATCH_END
+ 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::func::call_construct(
+ alloc, boost::unordered::detail::func::const_cast_pointer(
+ 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::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_CATCH_END
+ return a.release();
+}
+
+template <typename Alloc, typename Key, BOOST_UNORDERED_EMPLACE_TEMPLATE>
+inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
+construct_node_pair_from_args(
+ Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_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_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_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_CATCH_END
+ return a.release();
+}
+}
+}
+}
+}
+
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
+// The 'iterator_detail' namespace was a misguided attempt at avoiding ADL
+// in the detail namespace. It didn't work because the template parameters
+// were in detail. I'm not changing it at the moment to be safe. I might
+// do in the future if I change the iterator types.
+namespace boost {
+namespace unordered {
+namespace iterator_detail {
+
+////////////////////////////////////////////////////////////////////////////
+// Iterators
+//
+// all no throw
+
+template <typename Node, typename Policy>
+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>
+ friend struct boost::unordered::iterator_detail::cl_iterator;
+
+ private:
+#endif
+ typedef typename Node::node_pointer node_pointer;
+ node_pointer ptr_;
+ std::size_t bucket_;
+ std::size_t bucket_count_;
+
+ public:
+ typedef typename Node::value_type value_type;
+
+ l_iterator() BOOST_NOEXCEPT : ptr_() {}
+
+ l_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT
+ : ptr_(n),
+ bucket_(b),
+ bucket_count_(c)
+ {
+ }
+
+ value_type& operator*() const { return ptr_->value(); }
+
+ value_type* operator->() const { return ptr_->value_ptr(); }
+
+ l_iterator& operator++()
+ {
+ ptr_ = static_cast<node_pointer>(ptr_->next_);
+ if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) != bucket_)
+ ptr_ = node_pointer();
+ return *this;
+ }
+
+ l_iterator operator++(int)
+ {
+ l_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ bool operator==(l_iterator x) const BOOST_NOEXCEPT
+ {
+ return ptr_ == x.ptr_;
+ }
+
+ bool operator!=(l_iterator x) const BOOST_NOEXCEPT
+ {
+ return ptr_ != x.ptr_;
+ }
+};
+
+template <typename Node, typename Policy>
+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>;
+
+ private:
+ typedef typename Node::node_pointer node_pointer;
+ node_pointer ptr_;
+ std::size_t bucket_;
+ std::size_t bucket_count_;
+
+ public:
+ typedef typename Node::value_type value_type;
+
+ cl_iterator() BOOST_NOEXCEPT : ptr_() {}
+
+ cl_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT
+ : ptr_(n),
+ bucket_(b),
+ bucket_count_(c)
+ {
+ }
+
+ cl_iterator(
+ boost::unordered::iterator_detail::l_iterator<Node, Policy> const& x)
+ BOOST_NOEXCEPT : ptr_(x.ptr_),
+ bucket_(x.bucket_),
+ bucket_count_(x.bucket_count_)
+ {
+ }
+
+ value_type const& operator*() const { return ptr_->value(); }
+
+ value_type const* operator->() const { return ptr_->value_ptr(); }
+
+ cl_iterator& operator++()
+ {
+ ptr_ = static_cast<node_pointer>(ptr_->next_);
+ if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) != bucket_)
+ ptr_ = node_pointer();
+ return *this;
+ }
+
+ cl_iterator operator++(int)
+ {
+ cl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(
+ cl_iterator const& x, cl_iterator const& y) BOOST_NOEXCEPT
+ {
+ return x.ptr_ == y.ptr_;
+ }
+
+ friend bool operator!=(
+ cl_iterator const& x, cl_iterator const& y) BOOST_NOEXCEPT
+ {
+ return x.ptr_ != y.ptr_;
+ }
+};
+
+template <typename Node>
+struct 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>
+ 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
+ typedef typename Node::node_pointer node_pointer;
+ node_pointer node_;
+
+ public:
+ typedef typename Node::value_type value_type;
+
+ iterator() BOOST_NOEXCEPT : node_() {}
+
+ explicit iterator(typename Node::link_pointer x) BOOST_NOEXCEPT
+ : node_(static_cast<node_pointer>(x))
+ {
+ }
+
+ value_type& operator*() const { return node_->value(); }
+
+ value_type* operator->() const { return node_->value_ptr(); }
+
+ iterator& operator++()
+ {
+ node_ = static_cast<node_pointer>(node_->next_);
+ return *this;
+ }
+
+ iterator operator++(int)
+ {
+ iterator tmp(node_);
+ node_ = static_cast<node_pointer>(node_->next_);
+ return tmp;
+ }
+
+ bool operator==(iterator const& x) const BOOST_NOEXCEPT
+ {
+ return node_ == x.node_;
+ }
+
+ bool operator!=(iterator const& x) const BOOST_NOEXCEPT
+ {
+ return node_ != x.node_;
+ }
+};
+
+template <typename Node>
+struct c_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::iterator<Node>;
+
+#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
+ typedef typename Node::node_pointer node_pointer;
+ typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
+ node_pointer node_;
+
+ public:
+ typedef typename Node::value_type value_type;
+
+ c_iterator() BOOST_NOEXCEPT : node_() {}
+
+ explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT
+ : node_(static_cast<node_pointer>(x))
+ {
+ }
+
+ c_iterator(n_iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {}
+
+ value_type const& operator*() const { return node_->value(); }
+
+ value_type const* operator->() const { return node_->value_ptr(); }
+
+ c_iterator& operator++()
+ {
+ node_ = static_cast<node_pointer>(node_->next_);
+ return *this;
+ }
+
+ c_iterator operator++(int)
+ {
+ c_iterator tmp(node_);
+ node_ = static_cast<node_pointer>(node_->next_);
+ return tmp;
+ }
+
+ friend bool operator==(
+ c_iterator const& x, c_iterator const& y) BOOST_NOEXCEPT
+ {
+ return x.node_ == y.node_;
+ }
+
+ friend bool operator!=(
+ c_iterator const& x, c_iterator const& y) BOOST_NOEXCEPT
+ {
+ return x.node_ != y.node_;
+ }
+};
+}
+}
+}
+
+namespace boost {
+namespace unordered {
+namespace detail {
+
+///////////////////////////////////////////////////////////////////
+//
+// Node Holder
+//
+// Temporary store for nodes. Deletes any that aren't used.
+
+template <typename NodeAlloc> struct node_holder
+{
+ private:
+ typedef NodeAlloc node_allocator;
+ typedef boost::unordered::detail::allocator_traits<NodeAlloc>
+ node_allocator_traits;
+ typedef typename node_allocator_traits::value_type node;
+ typedef typename node_allocator_traits::pointer node_pointer;
+ typedef typename node::value_type value_type;
+ typedef typename node::link_pointer link_pointer;
+ typedef boost::unordered::iterator_detail::iterator<node> iterator;
+
+ node_constructor<NodeAlloc> constructor_;
+ node_pointer nodes_;
+
+ public:
+ template <typename Table>
+ explicit node_holder(Table& b) : constructor_(b.node_alloc()), nodes_()
+ {
+ if (b.size_) {
+ typename Table::link_pointer prev = b.get_previous_start();
+ nodes_ = static_cast<node_pointer>(prev->next_);
+ prev->next_ = link_pointer();
+ b.size_ = 0;
+ }
+ }
+
+ ~node_holder();
+
+ node_pointer pop_node()
+ {
+ node_pointer n = nodes_;
+ nodes_ = static_cast<node_pointer>(nodes_->next_);
+ n->init(n);
+ n->next_ = link_pointer();
+ return n;
+ }
+
+ template <typename T> inline node_pointer copy_of(T const& v)
+ {
+ if (nodes_) {
+ constructor_.reclaim(pop_node());
+ } else {
+ constructor_.create_node();
+ }
+ boost::unordered::detail::func::call_construct(
+ constructor_.alloc_, constructor_.node_->value_ptr(), v);
+ return constructor_.release();
+ }
+
+ template <typename T> inline node_pointer move_copy_of(T& v)
+ {
+ if (nodes_) {
+ constructor_.reclaim(pop_node());
+ } else {
+ constructor_.create_node();
+ }
+ boost::unordered::detail::func::call_construct(constructor_.alloc_,
+ constructor_.node_->value_ptr(), boost::move(v));
+ return constructor_.release();
+ }
+
+ iterator begin() const { return iterator(nodes_); }
+};
+
+template <typename Alloc> node_holder<Alloc>::~node_holder()
+{
+ while (nodes_) {
+ 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));
+ node_allocator_traits::deallocate(constructor_.alloc_, p, 1);
+ }
+}
+
+///////////////////////////////////////////////////////////////////
+//
+// Bucket
+
+template <typename NodePointer> struct bucket
+{
+ typedef NodePointer link_pointer;
+ link_pointer next_;
+
+ bucket() : next_() {}
+
+ link_pointer first_from_start() { return next_; }
+
+ enum
+ {
+ extra_node = true
+ };
+};
+
+struct ptr_bucket
+{
+ typedef ptr_bucket* link_pointer;
+ link_pointer next_;
+
+ ptr_bucket() : next_(0) {}
+
+ link_pointer first_from_start() { return this; }
+
+ enum
+ {
+ extra_node = false
+ };
+};
+
+///////////////////////////////////////////////////////////////////
+//
+// Hash Policy
+
+template <typename SizeT> struct prime_policy
+{
+ template <typename Hash, typename T>
+ static inline SizeT apply_hash(Hash const& hf, T const& x)
+ {
+ return hf(x);
+ }
+
+ static inline SizeT to_bucket(SizeT bucket_count, SizeT hash)
+ {
+ return hash % bucket_count;
+ }
+
+ static inline SizeT new_bucket_count(SizeT min)
+ {
+ return boost::unordered::detail::next_prime(min);
+ }
+
+ static inline SizeT prev_bucket_count(SizeT max)
+ {
+ return boost::unordered::detail::prev_prime(max);
+ }
+};
+
+template <typename SizeT> struct mix64_policy
+{
+ template <typename Hash, typename T>
+ static inline SizeT apply_hash(Hash const& hf, T const& x)
+ {
+ SizeT key = hf(x);
+ key = (~key) + (key << 21); // key = (key << 21) - key - 1;
+ key = key ^ (key >> 24);
+ key = (key + (key << 3)) + (key << 8); // key * 265
+ key = key ^ (key >> 14);
+ key = (key + (key << 2)) + (key << 4); // key * 21
+ key = key ^ (key >> 28);
+ key = key + (key << 31);
+ return key;
+ }
+
+ static inline SizeT to_bucket(SizeT bucket_count, SizeT hash)
+ {
+ return hash & (bucket_count - 1);
+ }
+
+ static inline SizeT new_bucket_count(SizeT min)
+ {
+ if (min <= 4)
+ return 4;
+ --min;
+ min |= min >> 1;
+ min |= min >> 2;
+ min |= min >> 4;
+ min |= min >> 8;
+ min |= min >> 16;
+ min |= min >> 32;
+ return min + 1;
+ }
+
+ static inline SizeT prev_bucket_count(SizeT max)
+ {
+ max |= max >> 1;
+ max |= max >> 2;
+ max |= max >> 4;
+ max |= max >> 8;
+ max |= max >> 16;
+ max |= max >> 32;
+ return (max >> 1) + 1;
+ }
+};
+
+template <int digits, int radix> struct pick_policy_impl
+{
+ typedef prime_policy<std::size_t> type;
+};
+
+template <> struct pick_policy_impl<64, 2>
+{
+ typedef mix64_policy<std::size_t> type;
+};
+
+template <typename T>
+struct pick_policy2 : pick_policy_impl<std::numeric_limits<std::size_t>::digits,
+ std::numeric_limits<std::size_t>::radix>
+{
+};
+
+// While the mix policy is generally faster, the prime policy is a lot
+// faster when a large number consecutive integers are used, because
+// there are no collisions. Since that is probably quite common, use
+// prime policy for integeral types. But not the smaller ones, as they
+// don't have enough unique values for this to be an issue.
+
+template <> struct pick_policy2<int>
+{
+ typedef prime_policy<std::size_t> type;
+};
+
+template <> struct pick_policy2<unsigned int>
+{
+ typedef prime_policy<std::size_t> type;
+};
+
+template <> struct pick_policy2<long>
+{
+ typedef prime_policy<std::size_t> type;
+};
+
+template <> struct pick_policy2<unsigned long>
+{
+ typedef prime_policy<std::size_t> type;
+};
+
+// TODO: Maybe not if std::size_t is smaller than long long.
+#if !defined(BOOST_NO_LONG_LONG)
+template <> struct pick_policy2<boost::long_long_type>
+{
+ typedef prime_policy<std::size_t> type;
+};
+
+template <> struct pick_policy2<boost::ulong_long_type>
+{
+ typedef prime_policy<std::size_t> type;
+};
+#endif
+
+template <typename T>
+struct pick_policy : pick_policy2<typename boost::remove_cv<T>::type>
+{
+};
+
+////////////////////////////////////////////////////////////////////////////
+// Functions
+
+// Assigning and swapping the equality and hash function objects
+// needs strong exception safety. To implement that normally we'd
+// require one of them to be known to not throw and the other to
+// guarantee strong exception safety. Unfortunately they both only
+// have basic exception safety. So to acheive strong exception
+// safety we have storage space for two copies, and assign the new
+// copies to the unused space. Then switch to using that to use
+// them. This is implemented in 'set_hash_functions' which
+// atomically assigns the new function objects in a strongly
+// exception safe manner.
+
+template <class H, class P, bool NoThrowMoveAssign> class set_hash_functions;
+
+template <class H, class P> class functions
+{
+ public:
+ static const bool nothrow_move_assignable =
+ boost::is_nothrow_move_assignable<H>::value &&
+ boost::is_nothrow_move_assignable<P>::value;
+ static const bool nothrow_move_constructible =
+ boost::is_nothrow_move_constructible<H>::value &&
+ boost::is_nothrow_move_constructible<P>::value;
+
+ private:
+ friend class boost::unordered::detail::set_hash_functions<H, P,
+ nothrow_move_assignable>;
+ functions& operator=(functions const&);
+
+ typedef compressed<H, P> function_pair;
+
+ typedef typename boost::aligned_storage<sizeof(function_pair),
+ boost::alignment_of<function_pair>::value>::type aligned_function;
+
+ bool current_; // The currently active functions.
+ aligned_function funcs_[2];
+
+ function_pair const& current() const
+ {
+ return *static_cast<function_pair const*>(
+ static_cast<void const*>(&funcs_[current_]));
+ }
+
+ function_pair& current()
+ {
+ return *static_cast<function_pair*>(
+ static_cast<void*>(&funcs_[current_]));
+ }
+
+ void construct(bool which, H const& hf, P const& eq)
+ {
+ new ((void*)&funcs_[which]) function_pair(hf, eq);
+ }
+
+ void construct(bool which, function_pair const& f,
+ boost::unordered::detail::false_type =
+ boost::unordered::detail::false_type())
+ {
+ new ((void*)&funcs_[which]) function_pair(f);
+ }
+
+ void construct(
+ bool which, function_pair& f, boost::unordered::detail::true_type)
+ {
+ new ((void*)&funcs_[which])
+ function_pair(f, boost::unordered::detail::move_tag());
+ }
+
+ void destroy(bool which)
+ {
+ boost::unordered::detail::func::destroy(
+ (function_pair*)(&funcs_[which]));
+ }
+
+ public:
+ typedef boost::unordered::detail::set_hash_functions<H, P,
+ nothrow_move_assignable>
+ set_hash_functions;
+
+ functions(H const& hf, P const& eq) : current_(false)
+ {
+ construct(current_, hf, eq);
+ }
+
+ functions(functions const& bf) : current_(false)
+ {
+ construct(current_, bf.current());
+ }
+
+ functions(functions& bf, boost::unordered::detail::move_tag)
+ : current_(false)
+ {
+ construct(current_, bf.current(),
+ boost::unordered::detail::integral_constant<bool,
+ nothrow_move_constructible>());
+ }
+
+ ~functions() { this->destroy(current_); }
+
+ H const& hash_function() const { return current().first(); }
+
+ P const& key_eq() const { return current().second(); }
+};
+
+template <class H, class P> class set_hash_functions<H, P, false>
+{
+ set_hash_functions(set_hash_functions const&);
+ set_hash_functions& operator=(set_hash_functions const&);
+
+ typedef functions<H, P> functions_type;
+
+ functions_type& functions_;
+ bool tmp_functions_;
+
+ public:
+ set_hash_functions(functions_type& f, H const& h, P const& p)
+ : functions_(f), tmp_functions_(!f.current_)
+ {
+ f.construct(tmp_functions_, h, p);
+ }
+
+ set_hash_functions(functions_type& f, functions_type const& other)
+ : functions_(f), tmp_functions_(!f.current_)
+ {
+ f.construct(tmp_functions_, other.current());
+ }
+
+ ~set_hash_functions() { functions_.destroy(tmp_functions_); }
+
+ void commit()
+ {
+ functions_.current_ = tmp_functions_;
+ tmp_functions_ = !tmp_functions_;
+ }
+};
+
+template <class H, class P> class set_hash_functions<H, P, true>
+{
+ set_hash_functions(set_hash_functions const&);
+ set_hash_functions& operator=(set_hash_functions const&);
+
+ typedef functions<H, P> functions_type;
+
+ functions_type& functions_;
+ H hash_;
+ P pred_;
+
+ public:
+ set_hash_functions(functions_type& f, H const& h, P const& p)
+ : functions_(f), hash_(h), pred_(p)
+ {
+ }
+
+ set_hash_functions(functions_type& f, functions_type const& other)
+ : functions_(f), hash_(other.hash_function()), pred_(other.key_eq())
+ {
+ }
+
+ void commit()
+ {
+ functions_.current().first() = boost::move(hash_);
+ functions_.current().second() = boost::move(pred_);
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////
+// rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
+// e.g. for int
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
+#else
+struct please_ignore_this_overload
+{
+ typedef please_ignore_this_overload type;
+};
+
+template <typename T> struct rv_ref_impl
+{
+ typedef BOOST_RV_REF(T) type;
+};
+
+template <typename T>
+struct rv_ref
+ : boost::detail::if_true<boost::is_class<T>::value>::BOOST_NESTED_TEMPLATE
+ then<boost::unordered::detail::rv_ref_impl<T>,
+ please_ignore_this_overload>::type
+{
+};
+
+#define BOOST_UNORDERED_RV_REF(T) \
+ typename boost::unordered::detail::rv_ref<T>::type
+#endif
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable : 4127) // conditional expression is constant
+#endif
+
+////////////////////////////////////////////////////////////////////////////
+// convert double to std::size_t
+
+inline std::size_t double_to_size(double f)
+{
+ return f >= static_cast<double>((std::numeric_limits<std::size_t>::max)())
+ ? (std::numeric_limits<std::size_t>::max)()
+ : static_cast<std::size_t>(f);
+}
+
+// The space used to store values in a node.
+
+template <typename ValueType> struct value_base
+{
+ typedef ValueType value_type;
+
+ typename boost::aligned_storage<sizeof(value_type),
+ boost::alignment_of<value_type>::value>::type data_;
+
+ value_base() : data_() {}
+
+ void* address() { return this; }
+
+ value_type& value() { return *(ValueType*)this; }
+
+ value_type const& value() const { return *(ValueType const*)this; }
+
+ value_type* value_ptr() { return (ValueType*)this; }
+
+ value_type const* value_ptr() const { return (ValueType const*)this; }
+
+ private:
+ value_base& operator=(value_base const&);
+};
+
+template <typename Types>
+struct table : boost::unordered::detail::functions<typename Types::hasher,
+ typename Types::key_equal>
+{
+ private:
+ table(table const&);
+ table& operator=(table const&);
+
+ public:
+ typedef typename Types::node node;
+ typedef typename Types::bucket bucket;
+ typedef typename Types::hasher hasher;
+ typedef typename Types::key_equal key_equal;
+ typedef typename Types::const_key_type const_key_type;
+ typedef typename Types::extractor extractor;
+ typedef typename Types::value_type value_type;
+ typedef typename Types::table table_impl;
+ typedef typename Types::link_pointer link_pointer;
+ typedef typename Types::policy policy;
+ typedef typename Types::iterator iterator;
+ 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>
+ functions;
+ typedef typename functions::set_hash_functions set_hash_functions;
+
+ typedef typename Types::value_allocator value_allocator;
+ typedef typename boost::unordered::detail::rebind_wrap<value_allocator,
+ node>::type node_allocator;
+ typedef typename boost::unordered::detail::rebind_wrap<value_allocator,
+ bucket>::type bucket_allocator;
+ typedef boost::unordered::detail::allocator_traits<node_allocator>
+ node_allocator_traits;
+ typedef boost::unordered::detail::allocator_traits<bucket_allocator>
+ bucket_allocator_traits;
+ typedef typename node_allocator_traits::pointer node_pointer;
+ typedef typename node_allocator_traits::const_pointer const_node_pointer;
+ typedef typename bucket_allocator_traits::pointer bucket_pointer;
+ typedef boost::unordered::detail::node_constructor<node_allocator>
+ node_constructor;
+ typedef boost::unordered::detail::node_tmp<node_allocator> node_tmp;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Members
+
+ boost::unordered::detail::compressed<bucket_allocator, node_allocator>
+ allocators_;
+ std::size_t bucket_count_;
+ std::size_t size_;
+ float mlf_;
+ std::size_t max_load_;
+ bucket_pointer buckets_;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Data access
+
+ bucket_allocator const& bucket_alloc() const { return allocators_.first(); }
+
+ node_allocator const& node_alloc() const { return allocators_.second(); }
+
+ bucket_allocator& bucket_alloc() { return allocators_.first(); }
+
+ node_allocator& node_alloc() { return allocators_.second(); }
+
+ std::size_t max_bucket_count() const
+ {
+ // -1 to account for the start bucket.
+ return policy::prev_bucket_count(
+ bucket_allocator_traits::max_size(bucket_alloc()) - 1);
+ }
+
+ bucket_pointer get_bucket(std::size_t bucket_index) const
+ {
+ BOOST_ASSERT(buckets_);
+ return buckets_ + static_cast<std::ptrdiff_t>(bucket_index);
+ }
+
+ link_pointer get_previous_start() const
+ {
+ return get_bucket(bucket_count_)->first_from_start();
+ }
+
+ link_pointer get_previous_start(std::size_t bucket_index) const
+ {
+ return get_bucket(bucket_index)->next_;
+ }
+
+ node_pointer begin() const
+ {
+ return size_ ? node_algo::next_node(get_previous_start())
+ : node_pointer();
+ }
+
+ node_pointer begin(std::size_t bucket_index) const
+ {
+ if (!size_)
+ return node_pointer();
+ link_pointer prev = get_previous_start(bucket_index);
+ return prev ? node_algo::next_node(prev) : node_pointer();
+ }
+
+ std::size_t hash_to_bucket(std::size_t hash_value) const
+ {
+ 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);
+ if (!n)
+ return 0;
+
+ std::size_t count = 0;
+ while (n && hash_to_bucket(n->hash_) == index) {
+ ++count;
+ n = node_algo::next_node(n);
+ }
+
+ return count;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // 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;
+
+ // From 6.3.1/13:
+ // Only resize when size >= mlf_ * count
+ max_load_ = buckets_ ? boost::unordered::detail::double_to_size(
+ ceil(static_cast<double>(mlf_) *
+ static_cast<double>(bucket_count_)))
+ : 0;
+ }
+
+ void max_load_factor(float z)
+ {
+ BOOST_ASSERT(z > 0);
+ mlf_ = (std::max)(z, minimum_max_load_factor);
+ recalculate_max_load();
+ }
+
+ std::size_t min_buckets_for_size(std::size_t size) const
+ {
+ BOOST_ASSERT(mlf_ >= minimum_max_load_factor);
+
+ using namespace std;
+
+ // From insert/emplace requirements:
+ //
+ // size <= mlf_ * count
+ // => count >= size / mlf_
+ //
+ // Or from rehash post-condition:
+ //
+ // count >= size / mlf_
+
+ return policy::new_bucket_count(
+ boost::unordered::detail::double_to_size(
+ floor(static_cast<double>(size) / static_cast<double>(mlf_)) +
+ 1));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Constructors
+
+ table(std::size_t num_buckets, hasher const& hf, key_equal const& eq,
+ node_allocator const& a)
+ : functions(hf, eq), allocators_(a, a),
+ bucket_count_(policy::new_bucket_count(num_buckets)), size_(0),
+ mlf_(1.0f), max_load_(0), buckets_()
+ {
+ }
+
+ table(table const& x, node_allocator const& a)
+ : functions(x), allocators_(a, a),
+ bucket_count_(x.min_buckets_for_size(x.size_)), size_(0),
+ mlf_(x.mlf_), max_load_(0), buckets_()
+ {
+ }
+
+ table(table& x, boost::unordered::detail::move_tag m)
+ : functions(x, m), allocators_(x.allocators_, m),
+ bucket_count_(x.bucket_count_), size_(x.size_), mlf_(x.mlf_),
+ max_load_(x.max_load_), buckets_(x.buckets_)
+ {
+ x.buckets_ = bucket_pointer();
+ x.size_ = 0;
+ x.max_load_ = 0;
+ }
+
+ 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_()
+ {
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Initialisation.
+
+ void init(table const& x)
+ {
+ if (x.size_) {
+ static_cast<table_impl*>(this)->copy_buckets(x);
+ }
+ }
+
+ void move_init(table& x)
+ {
+ 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);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Create buckets
+
+ 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));
+ }
+
+ bucket_allocator_traits::deallocate(
+ bucket_alloc(), new_buckets, length);
+
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+
+ bucket_count_ = new_count;
+ buckets_ = new_buckets;
+ recalculate_max_load();
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Swap and Move
+
+ void swap_allocators(table& other, false_type)
+ {
+ boost::unordered::detail::func::ignore_unused_variable_warning(other);
+
+ // According to 23.2.1.8, if propagate_on_container_swap is
+ // false the behaviour is undefined unless the allocators
+ // are equal.
+ BOOST_ASSERT(node_alloc() == other.node_alloc());
+ }
+
+ void swap_allocators(table& other, true_type)
+ {
+ allocators_.swap(other.allocators_);
+ }
+
+ // Only swaps the allocators if propagate_on_container_swap
+ void swap(table& x)
+ {
+ set_hash_functions op1(*this, x);
+ set_hash_functions op2(x, *this);
+
+ // I think swap can throw if Propagate::value,
+ // since the allocators' swap can throw. Not sure though.
+ swap_allocators(x, boost::unordered::detail::integral_constant<bool,
+ allocator_traits<node_allocator>::
+ propagate_on_container_swap::value>());
+
+ boost::swap(buckets_, x.buckets_);
+ boost::swap(bucket_count_, x.bucket_count_);
+ boost::swap(size_, x.size_);
+ std::swap(mlf_, x.mlf_);
+ std::swap(max_load_, x.max_load_);
+ op1.commit();
+ op2.commit();
+ }
+
+ // Only call with nodes allocated with the currect allocator, or
+ // one that is equal to it. (Can't assert because other's
+ // allocators might have already been moved).
+ void move_buckets_from(table& other)
+ {
+ BOOST_ASSERT(!buckets_);
+ buckets_ = other.buckets_;
+ bucket_count_ = other.bucket_count_;
+ size_ = other.size_;
+ other.buckets_ = bucket_pointer();
+ other.size_ = 0;
+ other.max_load_ = 0;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Delete/destruct
+
+ ~table() { delete_buckets(); }
+
+ void delete_node(link_pointer prev)
+ {
+ 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));
+ 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());
+
+ 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_allocator_traits::deallocate(node_alloc(), n, 1);
+ }
+
+ 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();
+ }
+ }
+
+ void destroy_buckets()
+ {
+ bucket_pointer end = get_bucket(bucket_count_ + 1);
+ for (bucket_pointer it = buckets_; it != end; ++it) {
+ boost::unordered::detail::func::destroy(boost::addressof(*it));
+ }
+
+ bucket_allocator_traits::deallocate(
+ bucket_alloc(), buckets_, bucket_count_ + 1);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Fix buckets after delete
+ //
+
+ std::size_t fix_bucket(std::size_t bucket_index, link_pointer prev)
+ {
+ 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 begin and end are in the same bucket, then
+ // there's nothing to do.
+ if (bucket_index == bucket_index2)
+ return bucket_index2;
+
+ // Update the bucket containing end.
+ 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)
+ this_bucket->next_ = link_pointer();
+
+ return bucket_index2;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Assignment
+
+ void assign(table const& x)
+ {
+ if (this != boost::addressof(x)) {
+ assign(x, boost::unordered::detail::integral_constant<bool,
+ allocator_traits<node_allocator>::
+ propagate_on_container_copy_assignment::value>());
+ }
+ }
+
+ void assign(table const& x, 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 {
+ clear_buckets();
+ }
+
+ new_func_this.commit();
+ static_cast<table_impl*>(this)->assign_buckets(x);
+ }
+
+ void assign(table const& x, true_type)
+ {
+ if (node_alloc() == x.node_alloc()) {
+ allocators_.assign(x.allocators_);
+ assign(x, false_type());
+ } else {
+ set_hash_functions new_func_this(*this, x);
+
+ // Delete everything with current allocators before assigning
+ // the new ones.
+ delete_buckets();
+ allocators_.assign(x.allocators_);
+
+ // Copy over other data, all no throw.
+ 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);
+ }
+ }
+ }
+
+ void move_assign(table& x)
+ {
+ if (this != boost::addressof(x)) {
+ move_assign(
+ x, boost::unordered::detail::integral_constant<bool,
+ allocator_traits<node_allocator>::
+ propagate_on_container_move_assignment::value>());
+ }
+ }
+
+ void move_assign(table& x, 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)
+ {
+ 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 {
+ 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 {
+ clear_buckets();
+ }
+
+ new_func_this.commit();
+ static_cast<table_impl*>(this)->move_assign_buckets(x);
+ }
+ }
+
+ // Accessors
+
+ const_key_type& get_key(value_type const& x) const
+ {
+ return extractor::extract(x);
+ }
+
+ std::size_t hash(const_key_type& k) const
+ {
+ return policy::apply_hash(this->hash_function(), k);
+ }
+
+ // 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());
+ }
+
+ node_pointer find_node(const_key_type& k) const
+ {
+ return this->find_node_impl(hash(k), k, this->key_eq());
+ }
+
+ template <class Key, class Pred>
+ node_pointer find_node_impl(
+ std::size_t key_hash, Key const& k, Pred const& eq) const
+ {
+ std::size_t bucket_index = this->hash_to_bucket(key_hash);
+ node_pointer n = this->begin(bucket_index);
+
+ for (;;) {
+ 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();
+ }
+
+ n = node_algo::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 prev = this->get_previous_start(bucket_index);
+ if (!prev) {
+ return prev;
+ }
+
+ for (;;) {
+ if (!prev->next_) {
+ return link_pointer();
+ }
+ 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);
+ }
+ }
+
+ // Extract and erase
+
+ inline node_pointer extract_by_key(const_key_type& k)
+ {
+ if (!this->size_) {
+ return node_pointer();
+ }
+ 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);
+ if (!prev) {
+ return node_pointer();
+ }
+ node_pointer n = node_algo::extract_first_node(prev);
+ --this->size_;
+ this->fix_bucket(bucket_index, prev);
+ n->next_ = link_pointer();
+
+ return n;
+ }
+
+ // Reserve and rehash
+
+ void reserve_for_insert(std::size_t);
+ 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));
+ }
+
+ // equals
+
+ bool equals(table_impl 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()));
+
+ if (!n2 || n1->value() != n2->value())
+ return false;
+ }
+
+ return true;
+ }
+
+ // Emplace/Insert
+
+ inline node_pointer add_node(node_pointer n, std::size_t key_hash)
+ {
+ n->hash_ = key_hash;
+
+ bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
+
+ 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;
+ }
+
+ b->next_ = start_node;
+ n->next_ = start_node->next_;
+ start_node->next_ = n;
+ } else {
+ n->next_ = b->next_->next_;
+ b->next_->next_ = n;
+ }
+
+ ++this->size_;
+ return n;
+ }
+
+ inline node_pointer resize_and_add_node(
+ 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
+ }
+
+ 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(
+ c_iterator hint, const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS)
+ {
+ if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
+ return iterator(hint.node_);
+ } else {
+ return emplace_impl(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
+ }
+ }
+
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ emplace_return emplace_impl(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);
+ if (pos) {
+ return emplace_return(iterator(pos), false);
+ } else {
+ return emplace_return(
+ iterator(this->resize_and_add_node(
+ boost::unordered::detail::func::construct_node_from_args(
+ this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
+ key_hash)),
+ true);
+ }
+ }
+
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ iterator emplace_hint_impl(
+ 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))) {
+ return iterator(hint.node_);
+ }
+ std::size_t key_hash = this->hash(k);
+ node_pointer pos = this->find_node(key_hash, k);
+ if (pos) {
+ return iterator(pos);
+ } else {
+ return iterator(this->resize_and_add_node(b.release(), key_hash));
+ }
+ }
+
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ emplace_return emplace_impl(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());
+ 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)),
+ true);
+ }
+ }
+
+ template <typename Key>
+ emplace_return try_emplace_impl(BOOST_FWD_REF(Key) k)
+ {
+ 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(
+ boost::unordered::detail::func::construct_node_pair(
+ this->node_alloc(), boost::forward<Key>(k)),
+ key_hash)),
+ true);
+ }
+ }
+
+ template <typename Key>
+ iterator try_emplace_hint_impl(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;
+ }
+ }
+
+ template <typename Key, BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ emplace_return try_emplace_impl(
+ BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS)
+ {
+ 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(
+ boost::unordered::detail::func::
+ construct_node_pair_from_args(this->node_alloc(),
+ boost::forward<Key>(k),
+ BOOST_UNORDERED_EMPLACE_FORWARD),
+ key_hash)),
+ true);
+ }
+ }
+
+ template <typename Key, BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ iterator try_emplace_hint_impl(
+ 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;
+ }
+ }
+
+ template <typename Key, typename M>
+ emplace_return insert_or_assign_impl(
+ BOOST_FWD_REF(Key) k, BOOST_FWD_REF(M) obj)
+ {
+ std::size_t key_hash = this->hash(k);
+ node_pointer pos = this->find_node(key_hash, k);
+
+ if (pos) {
+ pos->value().second = boost::forward<M>(obj);
+ return emplace_return(iterator(pos), false);
+ } else {
+ return emplace_return(
+ iterator(this->resize_and_add_node(
+ boost::unordered::detail::func::construct_node_pair(
+ this->node_alloc(), boost::forward<Key>(k),
+ boost::forward<M>(obj)),
+ key_hash)),
+ true);
+ }
+ }
+
+ template <typename NodeType, typename InsertReturnType>
+ void move_insert_node_type(NodeType& np, InsertReturnType& result)
+ {
+ if (np) {
+ const_key_type& k = this->get_key(np.ptr_->value());
+ std::size_t key_hash = this->hash(k);
+ node_pointer pos = this->find_node(key_hash, k);
+
+ if (pos) {
+ result.node = boost::move(np);
+ result.position = iterator(pos);
+ } else {
+ this->reserve_for_insert(this->size_ + 1);
+ result.position = iterator(this->add_node(np.ptr_, key_hash));
+ result.inserted = true;
+ np.ptr_ = node_pointer();
+ }
+ }
+ }
+
+ template <typename NodeType>
+ iterator move_insert_node_type_with_hint(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))) {
+ 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);
+ np.ptr_ = node_pointer();
+ }
+ return iterator(pos);
+ }
+
+ template <typename Types2>
+ void merge_impl(boost::unordered::detail::table<Types2>& other)
+ {
+ typedef boost::unordered::detail::table<Types2> other_table;
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<node, typename other_table::node>::value));
+ BOOST_ASSERT(this->node_alloc() == other.node_alloc());
+
+ if (other.size_) {
+ 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());
+ std::size_t key_hash = this->hash(k);
+ node_pointer pos = this->find_node(key_hash, k);
+
+ if (pos) {
+ 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_;
+ --other.size_;
+ other.fix_bucket(other.hash_to_bucket(n->hash_), prev);
+ this->add_node(n, key_hash);
+ }
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Insert range methods
+ //
+ // 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)
+ {
+ insert_range_impl2(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);
+ }
+ }
+
+ template <class InputIt>
+ void insert_range_impl2(const_key_type& k, InputIt i, InputIt j)
+ {
+ // No side effects in this initial code
+ std::size_t key_hash = this->hash(k);
+ node_pointer pos = this->find_node(key_hash, k);
+
+ if (!pos) {
+ node_tmp b(boost::unordered::detail::func::construct_node(
+ this->node_alloc(), *i),
+ this->node_alloc());
+ 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);
+ }
+ }
+
+ template <class InputIt>
+ void insert_range_impl(no_key, InputIt i, InputIt j)
+ {
+ node_constructor a(this->node_alloc());
+
+ do {
+ if (!a.node_) {
+ a.create_node();
+ }
+ boost::unordered::detail::func::call_construct(
+ a.alloc_, a.node_->value_ptr(), *i);
+ node_tmp b(a.release(), a.alloc_);
+
+ const_key_type& k = this->get_key(b.node_->value());
+ std::size_t key_hash = this->hash(k);
+ node_pointer pos = this->find_node(key_hash, k);
+
+ if (pos) {
+ a.reclaim(b.release());
+ } else {
+ // 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);
+ }
+ } while (++i != j);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Extract
+
+ inline node_pointer extract_by_iterator(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);
+ link_pointer prev = this->get_previous_start(bucket_index);
+ while (prev->next_ != n) {
+ prev = prev->next_;
+ }
+ prev->next_ = n->next_;
+ --this->size_;
+ this->fix_bucket(bucket_index, prev);
+ n->next_ = link_pointer();
+ return n;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Erase
+ //
+ // no throw
+
+ std::size_t erase_key(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);
+ if (!prev)
+ return 0;
+ link_pointer end = node_algo::next_node(prev)->next_;
+ this->delete_nodes(prev, end);
+ this->fix_bucket(bucket_index, prev);
+ return 1;
+ }
+
+ iterator erase(c_iterator r)
+ {
+ 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_);
+
+ // Find the node before i.
+ link_pointer prev = this->get_previous_start(bucket_index);
+ while (prev->next_ != i)
+ prev = prev->next_;
+
+ // Delete the nodes.
+ do {
+ this->delete_node(prev);
+ bucket_index = this->fix_bucket(bucket_index, prev);
+ } while (prev->next_ != j);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // fill_buckets
+
+ void copy_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(), n->value()),
+ n->hash_);
+ }
+ }
+
+ 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_);
+ }
+ }
+
+ void assign_buckets(table const& src)
+ {
+ 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_);
+ }
+ }
+
+ void move_assign_buckets(table& src)
+ {
+ 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;
+ }
+ 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));
+ }
+
+ // Equality
+
+ bool equals(grouped_table_impl 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()));
+ 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))
+ return false;
+ n1 = end1;
+ }
+
+ return true;
+ }
+
+ static bool group_equals(
+ 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);
+
+ if (n1 == end1)
+ return n2 == end2;
+ if (n2 == end2)
+ return false;
+ }
+
+ for (node_pointer n1a = n1, n2a = n2;;) {
+ n1a = node_algo::next_node(n1a);
+ n2a = node_algo::next_node(n2a);
+
+ if (n1a == end1) {
+ if (n2a == end2)
+ break;
+ else
+ return false;
+ }
+
+ if (n2a == end2)
+ return false;
+ }
+
+ node_pointer start = n1;
+ for (; n1 != end1; n1 = node_algo::next_node(n1)) {
+ value_type const& v = n1->value();
+ if (!find(start, n1, v)) {
+ std::size_t matches = count_equal(n2, end2, v);
+ if (!matches)
+ return false;
+ if (matches !=
+ 1 + count_equal(node_algo::next_node(n1), end1, v))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ static bool find(node_pointer n, node_pointer end, value_type const& v)
+ {
+ for (; n != end; n = node_algo::next_node(n))
+ if (n->value() == v)
+ return true;
+ return false;
+ }
+
+ static std::size_t count_equal(
+ node_pointer n, node_pointer end, value_type const& v)
+ {
+ std::size_t count = 0;
+ for (; n != end; n = node_algo::next_node(n))
+ if (n->value() == v)
+ ++count;
+ return count;
+ }
+
+ // Emplace/Insert
+
+ inline node_pointer add_node(
+ node_pointer n, std::size_t key_hash, node_pointer pos)
+ {
+ n->hash_ = key_hash;
+ if (pos) {
+ node_algo::add_to_node_group(n, pos);
+ 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)) {
+ this->get_bucket(next_bucket)->next_ = n;
+ }
+ }
+ } else {
+ bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
+
+ 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;
+ }
+
+ b->next_ = start_node;
+ n->next_ = start_node->next_;
+ start_node->next_ = n;
+ } else {
+ n->next_ = b->next_->next_;
+ b->next_->next_ = n;
+ }
+ }
+ ++this->size_;
+ return n;
+ }
+
+ inline node_pointer add_using_hint(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_)) {
+ this->get_bucket(next_bucket)->next_ = n;
+ }
+ }
+ ++this->size_;
+ 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)
+ {
+ node_tmp a(n, this->node_alloc());
+ const_key_type& k = this->get_key(a.node_->value());
+ 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));
+ }
+
+ iterator emplace_hint_impl(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))) {
+ this->reserve_for_insert(this->size_ + 1);
+ return iterator(this->add_using_hint(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));
+ }
+ }
+
+ void emplace_impl_no_rehash(node_pointer n)
+ {
+ node_tmp a(n, this->node_alloc());
+ const_key_type& k = this->get_key(a.node_->value());
+ 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);
+ }
+
+ template <typename NodeType> iterator move_insert_node_type(NodeType& np)
+ {
+ iterator result;
+
+ if (np) {
+ const_key_type& k = this->get_key(np.ptr_->value());
+ 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));
+ np.ptr_ = node_pointer();
+ }
+
+ return result;
+ }
+
+ template <typename NodeType>
+ iterator move_insert_node_type_with_hint(c_iterator hint, NodeType& np)
+ {
+ iterator result;
+
+ if (np) {
+ const_key_type& k = this->get_key(np.ptr_->value());
+
+ if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
+ this->reserve_for_insert(this->size_ + 1);
+ result = iterator(this->add_using_hint(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));
+ }
+ np.ptr_ = node_pointer();
+ }
+
+ return result;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Insert range methods
+
+ // if hash function throws, or inserting > 1 element, basic exception
+ // safety. Strong otherwise
+ template <class I>
+ void insert_range(I i, I j,
+ typename boost::unordered::detail::enable_if_forward<I, void*>::type =
+ 0)
+ {
+ if (i == j)
+ return;
+
+ std::size_t distance = static_cast<std::size_t>(std::distance(i, j));
+ if (distance == 1) {
+ emplace_impl(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(
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), *i));
+ }
+ }
+ }
+
+ template <class I>
+ void insert_range(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(
+ this->node_alloc(), *i));
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Extract
+
+ inline node_pointer extract_by_iterator(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);
+ }
+ }
+
+ prev->next_ = i->next_;
+ --this->size_;
+ this->fix_bucket(bucket_index, prev);
+ i->next_ = link_pointer();
+
+ return i;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Erase
+ //
+ // no throw
+
+ std::size_t erase_key(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);
+ 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);
+ return deleted_count;
+ }
+
+ iterator erase(c_iterator r)
+ {
+ 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_);
+ }
+
+ 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);
+ }
+ }
+
+ // Delete the nodes.
+ // Is it inefficient to call fix_bucket for every node?
+ do {
+ this->delete_node(prev);
+ bucket_index = this->fix_bucket(bucket_index, prev);
+ } while (prev->next_ != j);
+
+ return prev;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // fill_buckets
+
+ void copy_buckets(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(), 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()),
+ key_hash, pos);
+ }
+ }
+ }
+
+ void move_buckets(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())),
+ key_hash, pos);
+ }
+ }
+ }
+
+ void assign_buckets(table const& src)
+ {
+ 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(
+ 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);
+ }
+ }
+ }
+
+ void move_assign_buckets(table& src)
+ {
+ 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(
+ 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);
+ }
+ }
+ }
+};
+}
+}
+}
+
+#endif
diff --git a/boost/unordered/detail/map.hpp b/boost/unordered/detail/map.hpp
index 14253ef49a..cb9a954bb2 100644
--- a/boost/unordered/detail/map.hpp
+++ b/boost/unordered/detail/map.hpp
@@ -3,77 +3,105 @@
// Distributed under the 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/unordered/detail/implementation.hpp>
#include <boost/unordered/unordered_map_fwd.hpp>
-#include <boost/unordered/detail/equivalent.hpp>
-#include <boost/unordered/detail/unique.hpp>
-
-namespace boost { namespace unordered { namespace detail {
- template <typename A, typename K, typename M, typename H, typename P>
- struct map
- {
- typedef boost::unordered::detail::map<A, K, M, H, P> types;
-
- typedef A allocator;
- typedef std::pair<K const, M> value_type;
- typedef H hasher;
- typedef P key_equal;
- typedef K key_type;
-
- typedef boost::unordered::detail::allocator_traits<allocator>
- traits;
- typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
- typedef typename pick::node node;
- typedef typename pick::bucket bucket;
- typedef typename pick::link_pointer link_pointer;
-
- typedef boost::unordered::detail::table_impl<types> table;
- typedef boost::unordered::detail::map_extractor<key_type, 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;
- };
-
- 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 A allocator;
- typedef std::pair<K const, M> value_type;
- typedef H hasher;
- typedef P key_equal;
- typedef K key_type;
-
- typedef boost::unordered::detail::allocator_traits<allocator> traits;
- typedef boost::unordered::detail::pick_grouped_node<allocator,
- value_type> pick;
- typedef typename pick::node node;
- typedef typename pick::bucket bucket;
- typedef typename pick::link_pointer link_pointer;
-
- typedef boost::unordered::detail::grouped_table_impl<types> table;
- typedef boost::unordered::detail::map_extractor<key_type, 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;
- };
-
-}}}
+
+namespace boost {
+namespace unordered {
+namespace detail {
+template <typename A, typename K, typename M, typename H, typename P> struct map
+{
+ typedef boost::unordered::detail::map<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;
+
+ typedef boost::unordered::detail::pick_node<A, value_type> pick;
+ 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::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;
+ 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
+{
+ typedef boost::unordered_map<K, M, H, P, A> container;
+ container x;
+ typename container::node_type node_type;
+ typename container::insert_return_type insert_return_type;
+};
+
+template <typename K, typename M, typename H, typename P, typename A>
+class instantiate_multimap
+{
+ typedef boost::unordered_multimap<K, M, H, P, A> container;
+ container x;
+ typename container::node_type node_type;
+};
+}
+}
+}
diff --git a/boost/unordered/detail/set.hpp b/boost/unordered/detail/set.hpp
index ccbc4c99a3..42e9cad7b5 100644
--- a/boost/unordered/detail/set.hpp
+++ b/boost/unordered/detail/set.hpp
@@ -3,73 +3,103 @@
// Distributed under the 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/unordered/detail/implementation.hpp>
#include <boost/unordered/unordered_set_fwd.hpp>
-#include <boost/unordered/detail/equivalent.hpp>
-#include <boost/unordered/detail/unique.hpp>
-
-namespace boost { namespace unordered { namespace detail {
- template <typename A, typename T, typename H, typename P>
- struct set
- {
- typedef boost::unordered::detail::set<A, T, H, P> types;
-
- typedef A allocator;
- typedef T value_type;
- typedef H hasher;
- typedef P key_equal;
- typedef T key_type;
-
- typedef boost::unordered::detail::allocator_traits<allocator> traits;
- typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
- typedef typename pick::node node;
- typedef typename pick::bucket bucket;
- typedef typename pick::link_pointer link_pointer;
-
- typedef boost::unordered::detail::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;
- };
-
- template <typename A, typename T, typename H, typename P>
- struct multiset
- {
- typedef boost::unordered::detail::multiset<A, T, H, P> types;
-
- typedef A allocator;
- typedef T value_type;
- typedef H hasher;
- typedef P key_equal;
- typedef T key_type;
-
- typedef boost::unordered::detail::allocator_traits<allocator> traits;
- typedef boost::unordered::detail::pick_grouped_node<allocator,
- value_type> pick;
- typedef typename pick::node node;
- typedef typename pick::bucket bucket;
- typedef typename pick::link_pointer link_pointer;
-
- 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;
- };
-}}}
+
+namespace boost {
+namespace unordered {
+namespace detail {
+template <typename A, typename T, typename H, typename P> struct set
+{
+ typedef boost::unordered::detail::set<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;
+
+ typedef boost::unordered::detail::pick_node<A, value_type> pick;
+ 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::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;
+ 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;
+ container x;
+ typename container::node_type node_type;
+ typename container::insert_return_type insert_return_type;
+};
+
+template <typename T, typename H, typename P, typename A>
+class instantiate_multiset
+{
+ typedef boost::unordered_multiset<T, H, P, A> container;
+ container x;
+ typename container::node_type node_type;
+};
+}
+}
+}
diff --git a/boost/unordered/detail/table.hpp b/boost/unordered/detail/table.hpp
deleted file mode 100644
index 1092d31f9f..0000000000
--- a/boost/unordered/detail/table.hpp
+++ /dev/null
@@ -1,794 +0,0 @@
-
-// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2011 Daniel James
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
-#define BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
-
-#include <boost/config.hpp>
-#if defined(BOOST_HAS_PRAGMA_ONCE)
-#pragma once
-#endif
-
-#include <boost/unordered/detail/buckets.hpp>
-
-#if defined(BOOST_MSVC)
-#pragma warning(push)
-#pragma warning(disable:4127) // conditional expression is constant
-#endif
-
-namespace boost { namespace unordered { namespace detail {
-
- ////////////////////////////////////////////////////////////////////////////
- // convert double to std::size_t
-
- inline std::size_t double_to_size(double f)
- {
- return f >= static_cast<double>(
- (std::numeric_limits<std::size_t>::max)()) ?
- (std::numeric_limits<std::size_t>::max)() :
- static_cast<std::size_t>(f);
- }
-
- // The space used to store values in a node.
-
- template <typename ValueType>
- struct value_base
- {
- typedef ValueType value_type;
-
- typename boost::aligned_storage<
- sizeof(value_type),
- boost::alignment_of<value_type>::value>::type data_;
-
- value_base() :
- data_()
- {}
-
- void* address() {
- return this;
- }
-
- value_type& value() {
- return *(ValueType*) this;
- }
-
- value_type* value_ptr() {
- return (ValueType*) this;
- }
-
- private:
-
- value_base& operator=(value_base const&);
- };
-
- template <typename Types>
- struct table :
- boost::unordered::detail::functions<
- typename Types::hasher,
- typename Types::key_equal>
- {
- private:
- table(table const&);
- table& operator=(table const&);
- public:
- typedef typename Types::node node;
- typedef typename Types::bucket bucket;
- typedef typename Types::hasher hasher;
- typedef typename Types::key_equal key_equal;
- typedef typename Types::key_type key_type;
- typedef typename Types::extractor extractor;
- typedef typename Types::value_type value_type;
- typedef typename Types::table table_impl;
- typedef typename Types::link_pointer link_pointer;
- typedef typename Types::policy policy;
- typedef typename Types::iterator iterator;
- typedef typename Types::c_iterator c_iterator;
- typedef typename Types::l_iterator l_iterator;
- typedef typename Types::cl_iterator cl_iterator;
-
- typedef boost::unordered::detail::functions<
- typename Types::hasher,
- typename Types::key_equal> functions;
- typedef typename functions::set_hash_functions set_hash_functions;
-
- typedef typename Types::allocator allocator;
- typedef typename boost::unordered::detail::
- rebind_wrap<allocator, node>::type node_allocator;
- typedef typename boost::unordered::detail::
- rebind_wrap<allocator, bucket>::type bucket_allocator;
- typedef boost::unordered::detail::allocator_traits<node_allocator>
- node_allocator_traits;
- typedef boost::unordered::detail::allocator_traits<bucket_allocator>
- bucket_allocator_traits;
- typedef typename node_allocator_traits::pointer
- node_pointer;
- typedef typename node_allocator_traits::const_pointer
- const_node_pointer;
- typedef typename bucket_allocator_traits::pointer
- bucket_pointer;
- typedef boost::unordered::detail::node_constructor<node_allocator>
- node_constructor;
- typedef boost::unordered::detail::node_tmp<node_allocator>
- node_tmp;
-
- ////////////////////////////////////////////////////////////////////////
- // Members
-
- boost::unordered::detail::compressed<bucket_allocator, node_allocator>
- allocators_;
- std::size_t bucket_count_;
- std::size_t size_;
- float mlf_;
- std::size_t max_load_;
- bucket_pointer buckets_;
-
- ////////////////////////////////////////////////////////////////////////
- // Node functions
-
- static inline node_pointer next_node(link_pointer n) {
- return static_cast<node_pointer>(n->next_);
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Data access
-
- bucket_allocator const& bucket_alloc() const
- {
- return allocators_.first();
- }
-
- node_allocator const& node_alloc() const
- {
- return allocators_.second();
- }
-
- bucket_allocator& bucket_alloc()
- {
- return allocators_.first();
- }
-
- node_allocator& node_alloc()
- {
- return allocators_.second();
- }
-
- std::size_t max_bucket_count() const
- {
- // -1 to account for the start bucket.
- return policy::prev_bucket_count(
- bucket_allocator_traits::max_size(bucket_alloc()) - 1);
- }
-
- bucket_pointer get_bucket(std::size_t bucket_index) const
- {
- BOOST_ASSERT(buckets_);
- return buckets_ + static_cast<std::ptrdiff_t>(bucket_index);
- }
-
- link_pointer get_previous_start() const
- {
- return get_bucket(bucket_count_)->first_from_start();
- }
-
- link_pointer get_previous_start(std::size_t bucket_index) const
- {
- return get_bucket(bucket_index)->next_;
- }
-
- node_pointer begin() const
- {
- return size_ ? next_node(get_previous_start()) : node_pointer();
- }
-
- node_pointer begin(std::size_t bucket_index) const
- {
- if (!size_) return node_pointer();
- link_pointer prev = get_previous_start(bucket_index);
- return prev ? next_node(prev) : node_pointer();
- }
-
- std::size_t hash_to_bucket(std::size_t hash_value) const
- {
- 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);
- if (!n) return 0;
-
- std::size_t count = 0;
- while(n && hash_to_bucket(n->hash_) == index)
- {
- ++count;
- n = next_node(n);
- }
-
- return count;
- }
-
- ////////////////////////////////////////////////////////////////////////
- // 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;
-
- // From 6.3.1/13:
- // Only resize when size >= mlf_ * count
- max_load_ = buckets_ ? boost::unordered::detail::double_to_size(ceil(
- static_cast<double>(mlf_) *
- static_cast<double>(bucket_count_)
- )) : 0;
-
- }
-
- void max_load_factor(float z)
- {
- BOOST_ASSERT(z > 0);
- mlf_ = (std::max)(z, minimum_max_load_factor);
- recalculate_max_load();
- }
-
- std::size_t min_buckets_for_size(std::size_t size) const
- {
- BOOST_ASSERT(mlf_ >= minimum_max_load_factor);
-
- using namespace std;
-
- // From 6.3.1/13:
- // size < mlf_ * count
- // => count > size / mlf_
- //
- // Or from rehash post-condition:
- // count > size / mlf_
-
- return policy::new_bucket_count(
- boost::unordered::detail::double_to_size(floor(
- static_cast<double>(size) /
- static_cast<double>(mlf_)) + 1));
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Constructors
-
- table(std::size_t num_buckets,
- hasher const& hf,
- key_equal const& eq,
- node_allocator const& a) :
- functions(hf, eq),
- allocators_(a,a),
- bucket_count_(policy::new_bucket_count(num_buckets)),
- size_(0),
- mlf_(1.0f),
- max_load_(0),
- buckets_()
- {}
-
- table(table const& x, node_allocator const& a) :
- functions(x),
- allocators_(a,a),
- bucket_count_(x.min_buckets_for_size(x.size_)),
- size_(0),
- mlf_(x.mlf_),
- max_load_(0),
- buckets_()
- {}
-
- table(table& x, boost::unordered::detail::move_tag m) :
- functions(x, m),
- allocators_(x.allocators_, m),
- bucket_count_(x.bucket_count_),
- size_(x.size_),
- mlf_(x.mlf_),
- max_load_(x.max_load_),
- buckets_(x.buckets_)
- {
- x.buckets_ = bucket_pointer();
- x.size_ = 0;
- x.max_load_ = 0;
- }
-
- 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_()
- {}
-
- ////////////////////////////////////////////////////////////////////////
- // Initialisation.
-
- void init(table const& x)
- {
- if (x.size_) {
- static_cast<table_impl*>(this)->copy_buckets(x);
- }
- }
-
- void move_init(table& x)
- {
- 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);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Create buckets
-
- 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));
- }
-
- bucket_allocator_traits::deallocate(bucket_alloc(),
- new_buckets, length);
-
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
-
- bucket_count_ = new_count;
- buckets_ = new_buckets;
- recalculate_max_load();
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Swap and Move
-
- void swap_allocators(table& other, false_type)
- {
- boost::unordered::detail::func::ignore_unused_variable_warning(other);
-
- // According to 23.2.1.8, if propagate_on_container_swap is
- // false the behaviour is undefined unless the allocators
- // are equal.
- BOOST_ASSERT(node_alloc() == other.node_alloc());
- }
-
- void swap_allocators(table& other, true_type)
- {
- allocators_.swap(other.allocators_);
- }
-
- // Only swaps the allocators if propagate_on_container_swap
- void swap(table& x)
- {
- set_hash_functions op1(*this, x);
- set_hash_functions op2(x, *this);
-
- // I think swap can throw if Propagate::value,
- // since the allocators' swap can throw. Not sure though.
- swap_allocators(x,
- boost::unordered::detail::integral_constant<bool,
- allocator_traits<node_allocator>::
- propagate_on_container_swap::value>());
-
- boost::swap(buckets_, x.buckets_);
- boost::swap(bucket_count_, x.bucket_count_);
- boost::swap(size_, x.size_);
- std::swap(mlf_, x.mlf_);
- std::swap(max_load_, x.max_load_);
- op1.commit();
- op2.commit();
- }
-
- // Only call with nodes allocated with the currect allocator, or
- // one that is equal to it. (Can't assert because other's
- // allocators might have already been moved).
- void move_buckets_from(table& other)
- {
- BOOST_ASSERT(!buckets_);
- buckets_ = other.buckets_;
- bucket_count_ = other.bucket_count_;
- size_ = other.size_;
- other.buckets_ = bucket_pointer();
- other.size_ = 0;
- other.max_load_ = 0;
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Delete/destruct
-
- ~table()
- {
- delete_buckets();
- }
-
- void delete_node(link_pointer prev)
- {
- 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));
- 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());
-
- 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_allocator_traits::deallocate(node_alloc(), n, 1);
- }
-
- 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();
- }
- }
-
- void destroy_buckets()
- {
- bucket_pointer end = get_bucket(bucket_count_ + 1);
- for(bucket_pointer it = buckets_; it != end; ++it)
- {
- boost::unordered::detail::func::destroy(
- boost::addressof(*it));
- }
-
- bucket_allocator_traits::deallocate(bucket_alloc(),
- buckets_, bucket_count_ + 1);
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Fix buckets after delete
- //
-
- std::size_t fix_bucket(std::size_t bucket_index, link_pointer prev)
- {
- 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 begin and end are in the same bucket, then
- // there's nothing to do.
- if (bucket_index == bucket_index2) return bucket_index2;
-
- // Update the bucket containing end.
- 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)
- this_bucket->next_ = link_pointer();
-
- return bucket_index2;
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Assignment
-
- void assign(table const& x)
- {
- if (this != boost::addressof(x))
- {
- assign(x,
- boost::unordered::detail::integral_constant<bool,
- allocator_traits<node_allocator>::
- propagate_on_container_copy_assignment::value>());
- }
- }
-
- void assign(table const& x, 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 {
- clear_buckets();
- }
-
- new_func_this.commit();
- static_cast<table_impl*>(this)->assign_buckets(x);
- }
-
- void assign(table const& x, true_type)
- {
- if (node_alloc() == x.node_alloc()) {
- allocators_.assign(x.allocators_);
- assign(x, false_type());
- }
- else {
- set_hash_functions new_func_this(*this, x);
-
- // Delete everything with current allocators before assigning
- // the new ones.
- delete_buckets();
- allocators_.assign(x.allocators_);
-
- // Copy over other data, all no throw.
- 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);
- }
- }
- }
-
- void move_assign(table& x)
- {
- if (this != boost::addressof(x))
- {
- move_assign(x,
- boost::unordered::detail::integral_constant<bool,
- allocator_traits<node_allocator>::
- propagate_on_container_move_assignment::value>());
- }
- }
-
- void move_assign(table& x, 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)
- {
- 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 {
- 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 {
- clear_buckets();
- }
-
- new_func_this.commit();
- static_cast<table_impl*>(this)->move_assign_buckets(x);
- }
- }
-
- // Accessors
-
- key_type const& get_key(value_type const& x) const
- {
- return extractor::extract(x);
- }
-
- std::size_t hash(key_type const& k) const
- {
- return policy::apply_hash(this->hash_function(), k);
- }
-
- // 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 static_cast<table_impl const*>(this)->
- find_node_impl(policy::apply_hash(hf, k), k, eq);
- }
-
- node_pointer find_node(
- std::size_t key_hash,
- key_type const& k) const
- {
- return static_cast<table_impl const*>(this)->
- find_node_impl(key_hash, k, this->key_eq());
- }
-
- node_pointer find_node(key_type const& k) const
- {
- return static_cast<table_impl const*>(this)->
- find_node_impl(hash(k), k, this->key_eq());
- }
-
- // Reserve and rehash
-
- void reserve_for_insert(std::size_t);
- void rehash(std::size_t);
- void reserve(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)));
- }
- // According to the standard this should be 'size >= max_load_',
- // but I think this is better, defect report filed.
- 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_)
- static_cast<table_impl*>(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_)
- static_cast<table_impl*>(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_)));
- }
-}}}
-
-#if defined(BOOST_MSVC)
-#pragma warning(pop)
-#endif
-
-#endif
diff --git a/boost/unordered/detail/unique.hpp b/boost/unordered/detail/unique.hpp
deleted file mode 100644
index e77b4c149e..0000000000
--- a/boost/unordered/detail/unique.hpp
+++ /dev/null
@@ -1,683 +0,0 @@
-
-// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2011 Daniel James
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
-#define BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
-
-#include <boost/config.hpp>
-#if defined(BOOST_HAS_PRAGMA_ONCE)
-#pragma once
-#endif
-
-#include <boost/unordered/detail/extract_key.hpp>
-#include <boost/throw_exception.hpp>
-#include <stdexcept>
-
-namespace boost { namespace unordered { namespace detail {
-
- template <typename A, typename T> struct unique_node;
- template <typename T> struct ptr_node;
- template <typename Types> struct table_impl;
-
- 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;
-
- 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;
-
- 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&);
- };
-
- // 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;
- };
-
- 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::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::key_type 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 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);
- }
-
- // Node functions.
-
- static inline node_pointer next_node(link_pointer n) {
- return static_cast<node_pointer>(n->next_);
- }
-
- // Accessors
-
- template <class Key, class Pred>
- node_pointer find_node_impl(
- std::size_t key_hash,
- Key const& k,
- Pred const& eq) const
- {
- std::size_t bucket_index = this->hash_to_bucket(key_hash);
- node_pointer n = this->begin(bucket_index);
-
- for (;;)
- {
- 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();
- }
-
- n = next_node(n);
- }
- }
-
- std::size_t count(key_type const& k) const
- {
- return this->find_node(k) ? 1 : 0;
- }
-
- value_type& at(key_type const& 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(key_type const& k) const
- {
- node_pointer n = this->find_node(k);
- return std::make_pair(iterator(n), iterator(n ? next_node(n) : n));
- }
-
- // equals
-
- bool equals(table_impl const& other) const
- {
- if(this->size_ != other.size_) return false;
-
- for(node_pointer n1 = this->begin(); n1; n1 = next_node(n1))
- {
- node_pointer n2 = other.find_node(other.get_key(n1->value()));
-
- if (!n2 || n1->value() != n2->value())
- return false;
- }
-
- return true;
- }
-
- // Emplace/Insert
-
- inline node_pointer add_node(
- node_pointer n,
- std::size_t key_hash)
- {
- n->hash_ = key_hash;
-
- bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
-
- if (!b->next_)
- {
- link_pointer start_node = this->get_previous_start();
-
- if (start_node->next_) {
- this->get_bucket(this->hash_to_bucket(
- next_node(start_node)->hash_)
- )->next_ = n;
- }
-
- b->next_ = start_node;
- n->next_ = start_node->next_;
- start_node->next_ = n;
- }
- else
- {
- n->next_ = b->next_->next_;
- b->next_->next_ = n;
- }
-
- ++this->size_;
- return n;
- }
-
- inline node_pointer resize_and_add_node(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);
- }
-
- value_type& operator[](key_type const& k)
- {
- std::size_t key_hash = this->hash(k);
- node_pointer pos = this->find_node(key_hash, k);
- if (pos) {
- return pos->value();
- }
- else {
- return this->resize_and_add_node(
- boost::unordered::detail::func::construct_node_pair(this->node_alloc(), k),
- key_hash)->value();
- }
- }
-
-#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
- }
-
- 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(c_iterator hint, key_type const& k,
- BOOST_UNORDERED_EMPLACE_ARGS)
- {
- if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
- return iterator(hint.node_);
- }
- else {
- return emplace_impl(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
- }
- }
-
- template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- emplace_return emplace_impl(key_type const& k,
- BOOST_UNORDERED_EMPLACE_ARGS)
- {
- 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(
- boost::unordered::detail::func::construct_node_from_args(
- this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
- key_hash)),
- true);
- }
- }
-
- template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- iterator emplace_hint_impl(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());
- key_type const& k = this->get_key(b.node_->value());
- if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
- return iterator(hint.node_);
- }
- std::size_t key_hash = this->hash(k);
- node_pointer pos = this->find_node(key_hash, k);
- if (pos) {
- return iterator(pos);
- }
- else {
- return iterator(this->resize_and_add_node(b.release(), key_hash));
- }
- }
-
- template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- emplace_return emplace_impl(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());
- key_type const& k = this->get_key(b.node_->value());
- 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)),
- true);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Insert range methods
- //
- // 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(key_type const& k, InputIt i, InputIt j)
- {
- insert_range_impl2(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);
- }
- }
-
- template <class InputIt>
- void insert_range_impl2(key_type const& k, InputIt i, InputIt j)
- {
- // No side effects in this initial code
- std::size_t key_hash = this->hash(k);
- node_pointer pos = this->find_node(key_hash, k);
-
- if (!pos) {
- node_tmp b(
- boost::unordered::detail::func::construct_node(this->node_alloc(), *i),
- this->node_alloc());
- 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);
- }
- }
-
- template <class InputIt>
- void insert_range_impl(no_key, InputIt i, InputIt j)
- {
- node_constructor a(this->node_alloc());
-
- do {
- if (!a.node_) { a.create_node(); }
- boost::unordered::detail::func::call_construct(
- a.alloc_, a.node_->value_ptr(), *i);
- node_tmp b(a.release(), a.alloc_);
-
- key_type const& k = this->get_key(b.node_->value());
- std::size_t key_hash = this->hash(k);
- node_pointer pos = this->find_node(key_hash, k);
-
- if (pos) {
- a.reclaim(b.release());
- }
- else {
- // 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);
- }
- } while(++i != j);
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Erase
- //
- // no throw
-
- std::size_t erase_key(key_type const& 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->get_previous_start(bucket_index);
- if (!prev) return 0;
-
- for (;;)
- {
- if (!prev->next_) return 0;
- std::size_t node_hash = next_node(prev)->hash_;
- if (this->hash_to_bucket(node_hash) != bucket_index)
- return 0;
- if (node_hash == key_hash &&
- this->key_eq()(k, this->get_key(
- next_node(prev)->value())))
- break;
- prev = prev->next_;
- }
-
- link_pointer end = next_node(prev)->next_;
-
- std::size_t deleted_count = this->delete_nodes(prev, end);
- this->fix_bucket(bucket_index, prev);
- return deleted_count;
- }
-
- iterator erase(c_iterator r)
- {
- BOOST_ASSERT(r.node_);
- node_pointer next = 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_);
-
- // Find the node before i.
- link_pointer prev = this->get_previous_start(bucket_index);
- while(prev->next_ != i) prev = prev->next_;
-
- // Delete the nodes.
- do {
- this->delete_node(prev);
- bucket_index = this->fix_bucket(bucket_index, prev);
- } while (prev->next_ != j);
- }
-
- ////////////////////////////////////////////////////////////////////////
- // fill_buckets
-
- void copy_buckets(table const& src) {
- this->create_buckets(this->bucket_count_);
-
- for(node_pointer n = src.begin(); n; n = next_node(n)) {
- this->add_node(
- boost::unordered::detail::func::construct_node(
- this->node_alloc(), n->value()), n->hash_);
- }
- }
-
- void move_buckets(table const& src) {
- this->create_buckets(this->bucket_count_);
-
- for(node_pointer n = src.begin(); n; n = next_node(n)) {
- this->add_node(
- boost::unordered::detail::func::construct_node(
- this->node_alloc(), boost::move(n->value())), n->hash_);
- }
- }
-
- void assign_buckets(table const& src)
- {
- node_holder<node_allocator> holder(*this);
- for(node_pointer n = src.begin(); n; n = next_node(n)) {
- this->add_node(holder.copy_of(n->value()), n->hash_);
- }
- }
-
- void move_assign_buckets(table& src)
- {
- node_holder<node_allocator> holder(*this);
- for(node_pointer n = src.begin(); n; n = next_node(n)) {
- this->add_node(holder.move_copy_of(n->value()), n->hash_);
- }
- }
-
- // strong otherwise exception safety
- void 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_)
- prev = place_in_bucket(*this, prev);
- }
-
- // Iterate through the nodes placing them in the correct buckets.
- // pre: prev->next_ is not null.
- static link_pointer place_in_bucket(table& dst, link_pointer prev)
- {
- node_pointer n = next_node(prev);
- bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(n->hash_));
-
- if (!b->next_) {
- b->next_ = prev;
- return n;
- }
- else {
- prev->next_ = n->next_;
- n->next_ = b->next_->next_;
- b->next_->next_ = n;
- return prev;
- }
- }
- };
-}}}
-
-#endif
diff --git a/boost/unordered/detail/util.hpp b/boost/unordered/detail/util.hpp
deleted file mode 100644
index cd722e4410..0000000000
--- a/boost/unordered/detail/util.hpp
+++ /dev/null
@@ -1,249 +0,0 @@
-
-// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2011 Daniel James
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
-#define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
-
-#include <boost/config.hpp>
-#if defined(BOOST_HAS_PRAGMA_ONCE)
-#pragma once
-#endif
-
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/is_empty.hpp>
-#include <boost/iterator/iterator_categories.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/detail/select_type.hpp>
-#include <boost/move/move.hpp>
-#include <boost/preprocessor/seq/size.hpp>
-#include <boost/preprocessor/seq/enum.hpp>
-#include <boost/swap.hpp>
-
-namespace boost { namespace unordered { namespace detail {
-
- static const float minimum_max_load_factor = 1e-3f;
- static const std::size_t default_bucket_count = 11;
- struct move_tag {};
- struct empty_emplace {};
-
- namespace func {
- template <class T>
- inline void ignore_unused_variable_warning(T const&) {}
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // iterator SFINAE
-
- template <typename I>
- struct is_forward :
- boost::is_convertible<
- typename boost::iterator_traversal<I>::type,
- boost::forward_traversal_tag>
- {};
-
- template <typename I, typename ReturnType>
- struct enable_if_forward :
- boost::enable_if_c<
- boost::unordered::detail::is_forward<I>::value,
- ReturnType>
- {};
-
- template <typename I, typename ReturnType>
- struct disable_if_forward :
- boost::disable_if_c<
- boost::unordered::detail::is_forward<I>::value,
- ReturnType>
- {};
-
- ////////////////////////////////////////////////////////////////////////////
- // primes
-
-#define BOOST_UNORDERED_PRIMES \
- (17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
- (97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \
- (1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \
- (49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \
- (1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul) \
- (50331653ul)(100663319ul)(201326611ul)(402653189ul)(805306457ul) \
- (1610612741ul)(3221225473ul)(4294967291ul)
-
- template<class T> struct prime_list_template
- {
- static std::size_t const value[];
-
-#if !defined(SUNPRO_CC)
- static std::ptrdiff_t const length;
-#else
- static std::ptrdiff_t const length
- = BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
-#endif
- };
-
- template<class T>
- std::size_t const prime_list_template<T>::value[] = {
- BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIMES)
- };
-
-#if !defined(SUNPRO_CC)
- template<class T>
- std::ptrdiff_t const prime_list_template<T>::length
- = BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
-#endif
-
-#undef BOOST_UNORDERED_PRIMES
-
- typedef prime_list_template<std::size_t> prime_list;
-
- // no throw
- inline std::size_t next_prime(std::size_t num) {
- std::size_t const* const prime_list_begin = prime_list::value;
- std::size_t const* const prime_list_end = prime_list_begin +
- prime_list::length;
- std::size_t const* bound =
- std::lower_bound(prime_list_begin, prime_list_end, num);
- if(bound == prime_list_end)
- bound--;
- return *bound;
- }
-
- // no throw
- inline std::size_t prev_prime(std::size_t num) {
- std::size_t const* const prime_list_begin = prime_list::value;
- std::size_t const* const prime_list_end = prime_list_begin +
- prime_list::length;
- std::size_t const* bound =
- std::upper_bound(prime_list_begin,prime_list_end, num);
- if(bound != prime_list_begin)
- bound--;
- return *bound;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // insert_size/initial_size
-
- template <class I>
- inline std::size_t insert_size(I i, I j, typename
- boost::unordered::detail::enable_if_forward<I, void*>::type = 0)
- {
- return static_cast<std::size_t>(std::distance(i, j));
- }
-
- template <class I>
- inline std::size_t insert_size(I, I, typename
- boost::unordered::detail::disable_if_forward<I, void*>::type = 0)
- {
- return 1;
- }
-
- template <class I>
- inline std::size_t initial_size(I i, I j,
- std::size_t num_buckets =
- boost::unordered::detail::default_bucket_count)
- {
- // TODO: Why +1?
- return (std::max)(
- boost::unordered::detail::insert_size(i, j) + 1,
- num_buckets);
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // compressed
-
- template <typename T, int Index>
- struct compressed_base : private T
- {
- compressed_base(T const& x) : T(x) {}
- compressed_base(T& x, move_tag) : T(boost::move(x)) {}
-
- T& get() { return *this; }
- T const& get() const { return *this; }
- };
-
- template <typename T, int Index>
- struct uncompressed_base
- {
- uncompressed_base(T const& x) : value_(x) {}
- uncompressed_base(T& x, move_tag) : value_(boost::move(x)) {}
-
- T& get() { return value_; }
- T const& get() const { return value_; }
- private:
- T value_;
- };
-
- template <typename T, int Index>
- struct generate_base
- : boost::detail::if_true<
- boost::is_empty<T>::value
- >:: BOOST_NESTED_TEMPLATE then<
- boost::unordered::detail::compressed_base<T, Index>,
- boost::unordered::detail::uncompressed_base<T, Index>
- >
- {};
-
- template <typename T1, typename T2>
- struct compressed
- : private boost::unordered::detail::generate_base<T1, 1>::type,
- private boost::unordered::detail::generate_base<T2, 2>::type
- {
- typedef typename generate_base<T1, 1>::type base1;
- typedef typename generate_base<T2, 2>::type base2;
-
- typedef T1 first_type;
- typedef T2 second_type;
-
- first_type& first() {
- return static_cast<base1*>(this)->get();
- }
-
- first_type const& first() const {
- return static_cast<base1 const*>(this)->get();
- }
-
- second_type& second() {
- return static_cast<base2*>(this)->get();
- }
-
- second_type const& second() const {
- return static_cast<base2 const*>(this)->get();
- }
-
- template <typename First, typename Second>
- compressed(First const& x1, Second const& x2)
- : base1(x1), base2(x2) {}
-
- compressed(compressed const& x)
- : base1(x.first()), base2(x.second()) {}
-
- compressed(compressed& x, move_tag m)
- : base1(x.first(), m), base2(x.second(), m) {}
-
- void assign(compressed const& x)
- {
- first() = x.first();
- second() = x.second();
- }
-
- void move_assign(compressed& x)
- {
- first() = boost::move(x.first());
- second() = boost::move(x.second());
- }
-
- void swap(compressed& x)
- {
- boost::swap(first(), x.first());
- boost::swap(second(), x.second());
- }
-
- private:
- // Prevent assignment just to make use of assign or
- // move_assign explicit.
- compressed& operator=(compressed const&);
- };
-}}}
-
-#endif
diff --git a/boost/unordered/unordered_map.hpp b/boost/unordered/unordered_map.hpp
index 101b1c1c91..64e5b1fdf8 100644
--- a/boost/unordered/unordered_map.hpp
+++ b/boost/unordered/unordered_map.hpp
@@ -14,10 +14,10 @@
#pragma once
#endif
-#include <boost/unordered/unordered_map_fwd.hpp>
-#include <boost/unordered/detail/map.hpp>
+#include <boost/core/explicit_operator_bool.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
+#include <boost/unordered/detail/map.hpp>
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
#include <initializer_list>
@@ -26,1817 +26,2186 @@
#if defined(BOOST_MSVC)
#pragma warning(push)
#if BOOST_MSVC >= 1400
-#pragma warning(disable:4396) //the inline specifier cannot be used when a
- // friend declaration refers to a specialization
- // of a function template
+#pragma warning(disable : 4396) // the inline specifier cannot be used when a
+// friend declaration refers to a specialization
+// of a function template
#endif
#endif
-namespace boost
-{
-namespace unordered
+namespace boost {
+namespace unordered {
+template <class K, class T, class H, class P, class A> class unordered_map
{
- template <class K, class T, class H, class P, class A>
- class unordered_map
- {
#if defined(BOOST_UNORDERED_USE_MOVE)
- BOOST_COPYABLE_AND_MOVABLE(unordered_map)
-#endif
-
- public:
-
- typedef K key_type;
- typedef std::pair<const K, T> value_type;
- typedef T mapped_type;
- typedef H hasher;
- typedef P key_equal;
- typedef A allocator_type;
-
- private:
-
- typedef boost::unordered::detail::map<A, K, T, H, P> types;
- typedef typename types::traits allocator_traits;
- typedef typename types::table table;
-
- public:
+ BOOST_COPYABLE_AND_MOVABLE(unordered_map)
+#endif
+ template <typename, typename, typename, typename, typename>
+ friend class unordered_multimap;
- typedef typename allocator_traits::pointer pointer;
- typedef typename allocator_traits::const_pointer const_pointer;
+ public:
+ typedef K key_type;
+ typedef std::pair<const K, T> value_type;
+ typedef T mapped_type;
+ typedef H hasher;
+ typedef P key_equal;
+ typedef A allocator_type;
- typedef value_type& reference;
- typedef value_type const& const_reference;
+ private:
+ 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 std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
+ public:
+ typedef typename value_allocator_traits::pointer pointer;
+ typedef typename value_allocator_traits::const_pointer const_pointer;
- 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 value_type& reference;
+ typedef value_type const& const_reference;
- private:
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
- table table_;
+ 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 types::node_type node_type;
+ typedef typename types::insert_return_type insert_return_type;
- public:
+ private:
+ table table_;
- // constructors
+ public:
+ // constructors
- unordered_map();
+ unordered_map();
- explicit unordered_map(
- size_type,
- const hasher& = hasher(),
- const key_equal& = key_equal(),
- const allocator_type& = allocator_type());
+ explicit unordered_map(size_type, const hasher& = hasher(),
+ const key_equal& = key_equal(),
+ const allocator_type& = allocator_type());
- explicit unordered_map(
- size_type,
- const allocator_type&);
+ explicit unordered_map(size_type, const allocator_type&);
- explicit unordered_map(
- size_type,
- const hasher&,
- const allocator_type&);
+ explicit unordered_map(size_type, const hasher&, const allocator_type&);
- explicit unordered_map(allocator_type const&);
+ explicit unordered_map(allocator_type const&);
- template <class InputIt>
- unordered_map(InputIt, InputIt);
+ 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& = 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 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 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 allocator_type&);
- // copy/move constructors
+ // copy/move constructors
- unordered_map(unordered_map const&);
+ unordered_map(unordered_map const&);
- unordered_map(unordered_map const&, allocator_type const&);
- unordered_map(BOOST_RV_REF(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_UNORDERED_USE_MOVE)
- unordered_map(BOOST_RV_REF(unordered_map) other)
- BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
- : table_(other.table_, boost::unordered::detail::move_tag())
- {
- }
+ 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())
- {
- }
+ unordered_map(unordered_map&& other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
+ : table_(other.table_, boost::unordered::detail::move_tag())
+ {
+ }
#endif
#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&);
- unordered_map(
- std::initializer_list<value_type>,
- size_type,
- const allocator_type&);
+ 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&);
+ unordered_map(
+ std::initializer_list<value_type>, size_type, const allocator_type&);
#endif
- // Destructor
+ // Destructor
- ~unordered_map() BOOST_NOEXCEPT;
+ ~unordered_map() BOOST_NOEXCEPT;
- // Assign
+// Assign
#if defined(BOOST_UNORDERED_USE_MOVE)
- unordered_map& operator=(BOOST_COPY_ASSIGN_REF(unordered_map) x)
- {
- table_.assign(x.table_);
- return *this;
- }
+ unordered_map& operator=(BOOST_COPY_ASSIGN_REF(unordered_map) x)
+ {
+ table_.assign(x.table_);
+ return *this;
+ }
- unordered_map& operator=(BOOST_RV_REF(unordered_map) x)
- {
- table_.move_assign(x.table_);
- return *this;
- }
+ unordered_map& operator=(BOOST_RV_REF(unordered_map) x)
+ {
+ table_.move_assign(x.table_);
+ return *this;
+ }
#else
- unordered_map& operator=(unordered_map const& x)
- {
- table_.assign(x.table_);
- return *this;
- }
+ unordered_map& operator=(unordered_map const& x)
+ {
+ table_.assign(x.table_);
+ return *this;
+ }
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- unordered_map& operator=(unordered_map&& x)
- {
- table_.move_assign(x.table_);
- return *this;
- }
+ unordered_map& operator=(unordered_map&& x)
+ {
+ table_.move_assign(x.table_);
+ return *this;
+ }
#endif
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- unordered_map& operator=(std::initializer_list<value_type>);
+ unordered_map& operator=(std::initializer_list<value_type>);
#endif
- allocator_type get_allocator() const BOOST_NOEXCEPT
- {
- return table_.node_alloc();
- }
+ allocator_type get_allocator() const BOOST_NOEXCEPT
+ {
+ return table_.node_alloc();
+ }
- // size and capacity
+ // size and capacity
- bool empty() const BOOST_NOEXCEPT
- {
- return table_.size_ == 0;
- }
+ bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
- size_type size() const BOOST_NOEXCEPT
- {
- return table_.size_;
- }
+ size_type size() const BOOST_NOEXCEPT { return table_.size_; }
- size_type max_size() const BOOST_NOEXCEPT;
+ size_type max_size() const BOOST_NOEXCEPT;
- // iterators
+ // iterators
- iterator begin() BOOST_NOEXCEPT
- {
- return iterator(table_.begin());
- }
+ iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); }
- const_iterator begin() const BOOST_NOEXCEPT
- {
- return const_iterator(table_.begin());
- }
+ const_iterator begin() const BOOST_NOEXCEPT
+ {
+ return const_iterator(table_.begin());
+ }
- iterator end() BOOST_NOEXCEPT
- {
- return iterator();
- }
+ iterator end() BOOST_NOEXCEPT { return iterator(); }
- const_iterator end() const BOOST_NOEXCEPT
- {
- return const_iterator();
- }
+ const_iterator end() const BOOST_NOEXCEPT { return const_iterator(); }
- const_iterator cbegin() const BOOST_NOEXCEPT
- {
- return const_iterator(table_.begin());
- }
+ const_iterator cbegin() const BOOST_NOEXCEPT
+ {
+ return const_iterator(table_.begin());
+ }
- const_iterator cend() const BOOST_NOEXCEPT
- {
- return const_iterator();
- }
+ const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
- // emplace
+ // extract
+
+ node_type extract(const_iterator position)
+ {
+ return node_type(
+ table_.extract_by_iterator(position), table_.node_alloc());
+ }
+
+ node_type extract(const key_type& k)
+ {
+ return node_type(table_.extract_by_key(k), table_.node_alloc());
+ }
+
+// 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)...);
- }
+ template <class... Args>
+ std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
+ {
+ return table_.emplace(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)...);
- }
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ return table_.emplace_hint(hint, boost::forward<Args>(args)...);
+ }
+
+ template <class... Args>
+ std::pair<iterator, bool> try_emplace(
+ key_type const& k, BOOST_FWD_REF(Args)... args)
+ {
+ return table_.try_emplace_impl(k, boost::forward<Args>(args)...);
+ }
+
+ template <class... Args>
+ iterator try_emplace(
+ const_iterator hint, key_type const& k, BOOST_FWD_REF(Args)... args)
+ {
+ return table_.try_emplace_hint_impl(
+ hint, k, boost::forward<Args>(args)...);
+ }
+
+ template <class... Args>
+ std::pair<iterator, bool> try_emplace(
+ BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
+ {
+ return table_.try_emplace_impl(
+ 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(Args)... args)
+ {
+ return table_.try_emplace_hint_impl(
+ hint, boost::move(k), boost::forward<Args>(args)...);
+ }
#else
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
- // 0 argument emplace requires special treatment in case
- // the container is instantiated with a value type that
- // doesn't have a default constructor.
+ // 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 this->emplace(boost::move(v));
- }
+ std::pair<iterator, bool> emplace(
+ boost::unordered::detail::empty_emplace =
+ boost::unordered::detail::empty_emplace(),
+ value_type v = value_type())
+ {
+ return this->emplace(boost::move(v));
+ }
- iterator emplace_hint(const_iterator hint,
- boost::unordered::detail::empty_emplace
- = boost::unordered::detail::empty_emplace(),
- value_type v = value_type()
- )
- {
- 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())
+ {
+ return this->emplace_hint(hint, boost::move(v));
+ }
#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 Key>
+ std::pair<iterator, bool> try_emplace(BOOST_FWD_REF(Key) k)
+ {
+ return table_.try_emplace_impl(boost::forward<Key>(k));
+ }
- 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 Key>
+ iterator try_emplace(const_iterator hint, BOOST_FWD_REF(Key) k)
+ {
+ return table_.try_emplace_hint_impl(hint, boost::forward<Key>(k));
+ }
- 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))
- );
- }
+ 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, 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>
+ 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, 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))
- );
- }
+ template <typename A0>
+ std::pair<iterator, bool> try_emplace(
+ key_type const& k, BOOST_FWD_REF(A0) a0)
+ {
+ return table_.try_emplace_impl(
+ k, boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)));
+ }
- 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))
- );
- }
+ template <typename A0>
+ iterator try_emplace(
+ const_iterator hint, key_type const& k, BOOST_FWD_REF(A0) a0)
+ {
+ return table_.try_emplace_hint_impl(
+ hint, k, boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)));
+ }
-#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) \
- )); \
- }
+ template <typename A0>
+ std::pair<iterator, bool> try_emplace(
+ 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_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_EMPLACE, _)
+ template <typename A0>
+ iterator try_emplace(
+ const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0)
+ {
+ return table_.try_emplace_hint_impl(
+ hint, boost::move(k), 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)));
+ }
+
+ 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>
+ 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(
+ 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)
+ {
+ return table_.try_emplace_hint_impl(
+ hint, k, boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0), boost::forward<A1>(a1)));
+ }
+
+ template <typename A0, typename 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_impl(
+ boost::move(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, 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),
+ 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)));
+ }
+
+ 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)));
+ }
+
+ 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_impl(
+ 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 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;
+ }
+
+ 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)
+ {
+ 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)));
+ }
+
+ 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(
+ 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))); \
+ } \
+ \
+ 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( \
+ 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, \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
+ { \
+ return table_.try_emplace_hint_impl(hint, 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, \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
+ { \
+ return table_.try_emplace_impl(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)> \
+ 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), \
+ 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, _)
#undef BOOST_UNORDERED_EMPLACE
#endif
- std::pair<iterator, bool> insert(value_type const& x)
- {
- return this->emplace(x);
- }
+ 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));
- }
+ 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, 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));
- }
+ 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));
+ }
+
+ template <class M>
+ iterator insert_or_assign(
+ const_iterator, key_type const& k, BOOST_FWD_REF(M) obj)
+ {
+ return table_.insert_or_assign_impl(k, boost::forward<M>(obj)).first;
+ }
+
+ template <class M>
+ std::pair<iterator, bool> insert_or_assign(
+ BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
+ {
+ return table_.insert_or_assign_impl(
+ boost::move(k), boost::forward<M>(obj));
+ }
+
+ template <class M>
+ iterator insert_or_assign(
+ 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))
+ .first;
+ }
- template <class InputIt> void insert(InputIt, InputIt);
+ template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- void insert(std::initializer_list<value_type>);
+ void insert(std::initializer_list<value_type>);
#endif
- iterator erase(const_iterator);
- size_type erase(const key_type&);
- iterator erase(const_iterator, const_iterator);
- void quick_erase(const_iterator it) { erase(it); }
- void erase_return_void(const_iterator it) { erase(it); }
+ 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);
+ }
- void clear();
- void swap(unordered_map&);
+ iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
+ {
+ return table_.move_insert_node_type_with_hint(hint, np);
+ }
- // observers
+#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);
- hasher hash_function() const;
- key_equal key_eq() const;
+ public:
+#endif
- mapped_type& operator[](const key_type&);
- mapped_type& at(const key_type&);
- mapped_type const& at(const key_type&) const;
+ iterator erase(const_iterator);
+ size_type erase(const key_type&);
+ iterator erase(const_iterator, const_iterator);
+ void quick_erase(const_iterator it) { erase(it); }
+ void erase_return_void(const_iterator it) { erase(it); }
- // lookup
+ void clear();
+ void swap(unordered_map&);
- iterator find(const key_type&);
- const_iterator find(const key_type&) const;
+ template <typename H2, typename P2>
+ void merge(boost::unordered_map<K, T, H2, P2, A>& source);
- template <class CompatibleKey, class CompatibleHash,
- class CompatiblePredicate>
- iterator find(
- CompatibleKey const&,
- CompatibleHash const&,
- CompatiblePredicate const&);
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename H2, typename P2>
+ void merge(boost::unordered_map<K, T, H2, P2, A>&& source);
+#endif
- template <class CompatibleKey, class CompatibleHash,
- class CompatiblePredicate>
- const_iterator find(
- CompatibleKey const&,
- CompatibleHash const&,
- CompatiblePredicate const&) const;
+#if BOOST_UNORDERED_INTEROPERABLE_NODES
+ template <typename H2, typename P2>
+ void merge(boost::unordered_multimap<K, T, H2, P2, A>& source);
- size_type count(const key_type&) const;
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename H2, typename P2>
+ void merge(boost::unordered_multimap<K, T, H2, P2, A>&& source);
+#endif
+#endif
- std::pair<iterator, iterator>
- equal_range(const key_type&);
- std::pair<const_iterator, const_iterator>
- equal_range(const key_type&) const;
+ // observers
- // bucket interface
+ hasher hash_function() const;
+ key_equal key_eq() const;
- size_type bucket_count() const BOOST_NOEXCEPT
- {
- return table_.bucket_count_;
- }
+ mapped_type& operator[](const key_type&);
+ mapped_type& at(const key_type&);
+ mapped_type const& at(const key_type&) const;
- size_type max_bucket_count() const BOOST_NOEXCEPT
- {
- return table_.max_bucket_count();
- }
+ // lookup
- size_type bucket_size(size_type) const;
+ iterator find(const key_type&);
+ const_iterator find(const key_type&) const;
- size_type bucket(const key_type& k) const
- {
- return table_.hash_to_bucket(table_.hash(k));
- }
+ template <class CompatibleKey, class CompatibleHash,
+ class CompatiblePredicate>
+ iterator find(CompatibleKey const&, CompatibleHash const&,
+ CompatiblePredicate const&);
- local_iterator begin(size_type n)
- {
- return local_iterator(
- table_.begin(n), n, table_.bucket_count_);
- }
+ template <class CompatibleKey, class CompatibleHash,
+ class CompatiblePredicate>
+ const_iterator find(CompatibleKey const&, CompatibleHash const&,
+ CompatiblePredicate const&) const;
- const_local_iterator begin(size_type n) const
- {
- return const_local_iterator(
- table_.begin(n), n, table_.bucket_count_);
- }
+ size_type count(const key_type&) const;
- local_iterator end(size_type)
- {
- return local_iterator();
- }
+ std::pair<iterator, iterator> equal_range(const key_type&);
+ std::pair<const_iterator, const_iterator> equal_range(
+ const key_type&) const;
- const_local_iterator end(size_type) const
- {
- return const_local_iterator();
- }
+ // bucket interface
- const_local_iterator cbegin(size_type n) const
- {
- return const_local_iterator(
- table_.begin(n), n, table_.bucket_count_);
- }
+ size_type bucket_count() const BOOST_NOEXCEPT
+ {
+ return table_.bucket_count_;
+ }
- const_local_iterator cend(size_type) const
- {
- return const_local_iterator();
- }
+ size_type max_bucket_count() const BOOST_NOEXCEPT
+ {
+ return table_.max_bucket_count();
+ }
- // hash policy
+ size_type bucket_size(size_type) const;
- float max_load_factor() const BOOST_NOEXCEPT
- {
- return table_.mlf_;
- }
+ size_type bucket(const key_type& k) const
+ {
+ return table_.hash_to_bucket(table_.hash(k));
+ }
- float load_factor() const BOOST_NOEXCEPT;
- void max_load_factor(float) BOOST_NOEXCEPT;
- void rehash(size_type);
- void reserve(size_type);
+ local_iterator begin(size_type n)
+ {
+ return local_iterator(table_.begin(n), n, table_.bucket_count_);
+ }
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
- friend bool operator==<K,T,H,P,A>(
- unordered_map const&, unordered_map const&);
- friend bool operator!=<K,T,H,P,A>(
- unordered_map const&, unordered_map const&);
-#endif
- }; // class template unordered_map
+ const_local_iterator begin(size_type n) const
+ {
+ return const_local_iterator(table_.begin(n), n, table_.bucket_count_);
+ }
+
+ local_iterator end(size_type) { return local_iterator(); }
- template <class K, class T, class H, class P, class A>
- class unordered_multimap
+ const_local_iterator end(size_type) const { return const_local_iterator(); }
+
+ const_local_iterator cbegin(size_type n) const
{
-#if defined(BOOST_UNORDERED_USE_MOVE)
- BOOST_COPYABLE_AND_MOVABLE(unordered_multimap)
-#endif
- public:
+ return const_local_iterator(table_.begin(n), n, table_.bucket_count_);
+ }
- typedef K key_type;
- typedef std::pair<const K, T> value_type;
- typedef T mapped_type;
- typedef H hasher;
- typedef P key_equal;
- typedef A allocator_type;
+ const_local_iterator cend(size_type) const
+ {
+ return const_local_iterator();
+ }
- private:
+ // hash policy
- typedef boost::unordered::detail::multimap<A, K, T, H, P> types;
- typedef typename types::traits allocator_traits;
- typedef typename types::table table;
+ float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
- public:
+ float load_factor() const BOOST_NOEXCEPT;
+ void max_load_factor(float) BOOST_NOEXCEPT;
+ void rehash(size_type);
+ void reserve(size_type);
- typedef typename allocator_traits::pointer pointer;
- typedef typename allocator_traits::const_pointer const_pointer;
+#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
+ friend bool operator==
+ <K, T, H, P, A>(unordered_map const&, unordered_map const&);
+ friend bool operator!=
+ <K, T, H, P, A>(unordered_map const&, unordered_map const&);
+#endif
+}; // class template unordered_map
- typedef value_type& reference;
- typedef value_type const& const_reference;
+template <class K, class T, class H, class P, class A> class unordered_multimap
+{
+#if defined(BOOST_UNORDERED_USE_MOVE)
+ BOOST_COPYABLE_AND_MOVABLE(unordered_multimap)
+#endif
+ template <typename, typename, typename, typename, typename>
+ friend class unordered_map;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
+ public:
+ typedef K key_type;
+ typedef std::pair<const K, T> value_type;
+ typedef T mapped_type;
+ typedef H hasher;
+ typedef P key_equal;
+ typedef A allocator_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;
+ private:
+ typedef boost::unordered::detail::multimap<A, K, T, H, P> types;
+ typedef typename types::value_allocator_traits value_allocator_traits;
+ typedef typename types::table table;
- private:
+ public:
+ typedef typename value_allocator_traits::pointer pointer;
+ typedef typename value_allocator_traits::const_pointer const_pointer;
- table table_;
-
- public:
+ typedef value_type& reference;
+ typedef value_type const& const_reference;
- // constructors
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
- unordered_multimap();
+ 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 types::node_type node_type;
- explicit unordered_multimap(
- size_type,
- const hasher& = hasher(),
- const key_equal& = key_equal(),
- const allocator_type& = allocator_type());
+ private:
+ table table_;
- explicit unordered_multimap(
- size_type,
- const allocator_type&);
+ public:
+ // constructors
- explicit unordered_multimap(
- size_type,
- const hasher&,
- const allocator_type&);
+ unordered_multimap();
- explicit unordered_multimap(allocator_type const&);
+ explicit unordered_multimap(size_type, const hasher& = hasher(),
+ const key_equal& = key_equal(),
+ const allocator_type& = allocator_type());
- template <class InputIt>
- unordered_multimap(InputIt, InputIt);
+ explicit unordered_multimap(size_type, const allocator_type&);
- template <class InputIt>
- unordered_multimap(
- InputIt, InputIt,
- size_type,
- const hasher& = hasher(),
- const key_equal& = key_equal());
+ explicit unordered_multimap(
+ size_type, const hasher&, const allocator_type&);
- template <class InputIt>
- unordered_multimap(
- InputIt, InputIt,
- size_type,
- const hasher&,
- const key_equal&,
- const allocator_type&);
+ explicit unordered_multimap(allocator_type const&);
- template <class InputIt>
- unordered_multimap(
- InputIt, InputIt,
- size_type,
- const hasher&,
- const allocator_type&);
+ template <class InputIt> unordered_multimap(InputIt, InputIt);
- template <class InputIt>
- unordered_multimap(
- InputIt, InputIt,
- size_type,
- const allocator_type&);
+ template <class InputIt>
+ unordered_multimap(InputIt, InputIt, size_type, const hasher& = hasher(),
+ const key_equal& = key_equal());
- // copy/move constructors
+ 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&);
- unordered_multimap(unordered_multimap const&);
+ // copy/move constructors
- unordered_multimap(unordered_multimap const&, allocator_type const&);
- unordered_multimap(BOOST_RV_REF(unordered_multimap), allocator_type const&);
+ 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)
- unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
- BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
- : table_(other.table_, boost::unordered::detail::move_tag())
- {
- }
+ 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())
- {
- }
+ unordered_multimap(unordered_multimap&& other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
+ : table_(other.table_, boost::unordered::detail::move_tag())
+ {
+ }
#endif
#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&);
- unordered_multimap(
- std::initializer_list<value_type>,
- size_type,
- const allocator_type&);
+ 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&);
+ unordered_multimap(
+ std::initializer_list<value_type>, size_type, const allocator_type&);
#endif
- // Destructor
+ // Destructor
- ~unordered_multimap() BOOST_NOEXCEPT;
+ ~unordered_multimap() BOOST_NOEXCEPT;
- // Assign
+// Assign
#if defined(BOOST_UNORDERED_USE_MOVE)
- unordered_multimap& operator=(
- BOOST_COPY_ASSIGN_REF(unordered_multimap) x)
- {
- table_.assign(x.table_);
- return *this;
- }
+ unordered_multimap& operator=(BOOST_COPY_ASSIGN_REF(unordered_multimap) x)
+ {
+ table_.assign(x.table_);
+ return *this;
+ }
- unordered_multimap& operator=(BOOST_RV_REF(unordered_multimap) x)
- {
- table_.move_assign(x.table_);
- return *this;
- }
+ unordered_multimap& operator=(BOOST_RV_REF(unordered_multimap) x)
+ {
+ table_.move_assign(x.table_);
+ return *this;
+ }
#else
- unordered_multimap& operator=(unordered_multimap const& x)
- {
- table_.assign(x.table_);
- return *this;
- }
+ unordered_multimap& operator=(unordered_multimap const& x)
+ {
+ table_.assign(x.table_);
+ return *this;
+ }
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- unordered_multimap& operator=(unordered_multimap&& x)
- {
- table_.move_assign(x.table_);
- return *this;
- }
+ unordered_multimap& operator=(unordered_multimap&& x)
+ {
+ table_.move_assign(x.table_);
+ return *this;
+ }
#endif
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- unordered_multimap& operator=(std::initializer_list<value_type>);
+ unordered_multimap& operator=(std::initializer_list<value_type>);
#endif
- allocator_type get_allocator() const BOOST_NOEXCEPT
- {
- return table_.node_alloc();
- }
+ allocator_type get_allocator() const BOOST_NOEXCEPT
+ {
+ return table_.node_alloc();
+ }
- // size and capacity
+ // size and capacity
- bool empty() const BOOST_NOEXCEPT
- {
- return table_.size_ == 0;
- }
+ bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
- size_type size() const BOOST_NOEXCEPT
- {
- return table_.size_;
- }
+ size_type size() const BOOST_NOEXCEPT { return table_.size_; }
- size_type max_size() const BOOST_NOEXCEPT;
+ size_type max_size() const BOOST_NOEXCEPT;
- // iterators
+ // iterators
- iterator begin() BOOST_NOEXCEPT
- {
- return iterator(table_.begin());
- }
+ iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); }
- const_iterator begin() const BOOST_NOEXCEPT
- {
- return const_iterator(table_.begin());
- }
+ const_iterator begin() const BOOST_NOEXCEPT
+ {
+ return const_iterator(table_.begin());
+ }
- iterator end() BOOST_NOEXCEPT
- {
- return iterator();
- }
+ iterator end() BOOST_NOEXCEPT { return iterator(); }
- const_iterator end() const BOOST_NOEXCEPT
- {
- return const_iterator();
- }
+ const_iterator end() const BOOST_NOEXCEPT { return const_iterator(); }
- const_iterator cbegin() const BOOST_NOEXCEPT
- {
- return const_iterator(table_.begin());
- }
+ const_iterator cbegin() const BOOST_NOEXCEPT
+ {
+ return const_iterator(table_.begin());
+ }
- const_iterator cend() const BOOST_NOEXCEPT
- {
- return const_iterator();
- }
+ const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
+
+ // extract
+
+ node_type extract(const_iterator position)
+ {
+ return node_type(
+ table_.extract_by_iterator(position), table_.node_alloc());
+ }
- // emplace
+ node_type extract(const key_type& k)
+ {
+ return node_type(table_.extract_by_key(k), table_.node_alloc());
+ }
+
+// 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)...);
- }
+ template <class... Args> iterator emplace(BOOST_FWD_REF(Args)... args)
+ {
+ return table_.emplace(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)...);
- }
+ 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))
- // 0 argument emplace requires special treatment in case
- // the container is instantiated with a value type that
- // doesn't have a default constructor.
+ // 0 argument emplace requires special treatment in case
+ // the container is instantiated with a value type that
+ // doesn't have a default constructor.
- iterator emplace(
- boost::unordered::detail::empty_emplace
- = boost::unordered::detail::empty_emplace(),
- value_type v = value_type())
- {
- return this->emplace(boost::move(v));
- }
+ iterator emplace(boost::unordered::detail::empty_emplace =
+ boost::unordered::detail::empty_emplace(),
+ value_type v = value_type())
+ {
+ return this->emplace(boost::move(v));
+ }
- iterator emplace_hint(const_iterator hint,
- boost::unordered::detail::empty_emplace
- = boost::unordered::detail::empty_emplace(),
- value_type v = value_type()
- )
- {
- 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())
+ {
+ return this->emplace_hint(hint, boost::move(v));
+ }
#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(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>
+ 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))
- );
- }
+ 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)));
+ }
- 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>
+ 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))
- );
- }
+ 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)));
+ }
- 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))
- );
- }
+ 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)));
+ }
-#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) \
- )); \
- } \
- \
- 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_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))); \
+ } \
+ \
+ 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, _)
+ BOOST_PP_REPEAT_FROM_TO(
+ 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE
#endif
- iterator insert(value_type const& x)
- {
- return this->emplace(x);
- }
+ iterator insert(value_type const& x) { return this->emplace(x); }
- iterator insert(BOOST_RV_REF(value_type) x)
- {
- return this->emplace(boost::move(x));
- }
+ iterator 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, 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));
- }
+ iterator insert(const_iterator hint, BOOST_RV_REF(value_type) x)
+ {
+ return this->emplace_hint(hint, boost::move(x));
+ }
- template <class InputIt> void insert(InputIt, InputIt);
+ template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- void insert(std::initializer_list<value_type>);
+ void insert(std::initializer_list<value_type>);
#endif
- iterator erase(const_iterator);
- size_type erase(const key_type&);
- iterator erase(const_iterator, const_iterator);
- void quick_erase(const_iterator it) { erase(it); }
- void erase_return_void(const_iterator it) { erase(it); }
-
- void clear();
- void swap(unordered_multimap&);
-
- // observers
-
- hasher hash_function() const;
- key_equal key_eq() const;
-
- // lookup
-
- iterator find(const key_type&);
- const_iterator find(const key_type&) const;
+ iterator insert(BOOST_RV_REF(node_type) np)
+ {
+ return table_.move_insert_node_type(np);
+ }
- template <class CompatibleKey, class CompatibleHash,
- class CompatiblePredicate>
- iterator find(
- CompatibleKey const&,
- CompatibleHash const&,
- CompatiblePredicate const&);
+ iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
+ {
+ return table_.move_insert_node_type_with_hint(hint, np);
+ }
- template <class CompatibleKey, class CompatibleHash,
- class CompatiblePredicate>
- const_iterator find(
- CompatibleKey const&,
- CompatibleHash const&,
- CompatiblePredicate const&) const;
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ private:
+ // Note: Use r-value node_type to insert.
+ iterator insert(node_type&);
+ iterator insert(const_iterator, node_type& np);
- size_type count(const key_type&) const;
+ public:
+#endif
- std::pair<iterator, iterator>
- equal_range(const key_type&);
- std::pair<const_iterator, const_iterator>
- equal_range(const key_type&) const;
+ iterator erase(const_iterator);
+ size_type erase(const key_type&);
+ iterator erase(const_iterator, const_iterator);
+ void quick_erase(const_iterator it) { erase(it); }
+ void erase_return_void(const_iterator it) { erase(it); }
- // bucket interface
+ void clear();
+ void swap(unordered_multimap&);
- size_type bucket_count() const BOOST_NOEXCEPT
- {
- return table_.bucket_count_;
- }
+ template <typename H2, typename P2>
+ void merge(boost::unordered_multimap<K, T, H2, P2, A>& source);
- size_type max_bucket_count() const BOOST_NOEXCEPT
- {
- return table_.max_bucket_count();
- }
-
- size_type bucket_size(size_type) const;
-
- size_type bucket(const key_type& k) const
- {
- return table_.hash_to_bucket(table_.hash(k));
- }
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename H2, typename P2>
+ void merge(boost::unordered_multimap<K, T, H2, P2, A>&& source);
+#endif
- local_iterator begin(size_type n)
- {
- return local_iterator(
- table_.begin(n), n, table_.bucket_count_);
- }
+#if BOOST_UNORDERED_INTEROPERABLE_NODES
+ template <typename H2, typename P2>
+ void merge(boost::unordered_map<K, T, H2, P2, A>& source);
- const_local_iterator begin(size_type n) const
- {
- return const_local_iterator(
- table_.begin(n), n, table_.bucket_count_);
- }
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename H2, typename P2>
+ void merge(boost::unordered_map<K, T, H2, P2, A>&& source);
+#endif
+#endif
- local_iterator end(size_type)
- {
- return local_iterator();
- }
+ // observers
- const_local_iterator end(size_type) const
- {
- return const_local_iterator();
- }
+ hasher hash_function() const;
+ key_equal key_eq() const;
- const_local_iterator cbegin(size_type n) const
- {
- return const_local_iterator(
- table_.begin(n), n, table_.bucket_count_);
- }
+ // lookup
- const_local_iterator cend(size_type) const
- {
- return const_local_iterator();
- }
+ iterator find(const key_type&);
+ const_iterator find(const key_type&) const;
- // hash policy
+ template <class CompatibleKey, class CompatibleHash,
+ class CompatiblePredicate>
+ iterator find(CompatibleKey const&, CompatibleHash const&,
+ CompatiblePredicate const&);
- float max_load_factor() const BOOST_NOEXCEPT
- {
- return table_.mlf_;
- }
+ template <class CompatibleKey, class CompatibleHash,
+ class CompatiblePredicate>
+ const_iterator find(CompatibleKey const&, CompatibleHash const&,
+ CompatiblePredicate const&) const;
- float load_factor() const BOOST_NOEXCEPT;
- void max_load_factor(float) BOOST_NOEXCEPT;
- void rehash(size_type);
- void reserve(size_type);
+ size_type count(const key_type&) const;
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
- friend bool operator==<K,T,H,P,A>(
- unordered_multimap const&, unordered_multimap const&);
- friend bool operator!=<K,T,H,P,A>(
- unordered_multimap const&, unordered_multimap const&);
-#endif
- }; // class template unordered_multimap
+ std::pair<iterator, iterator> equal_range(const key_type&);
+ std::pair<const_iterator, const_iterator> equal_range(
+ const key_type&) const;
-////////////////////////////////////////////////////////////////////////////////
+ // bucket interface
- template <class K, class T, class H, class P, class A>
- unordered_map<K,T,H,P,A>::unordered_map()
- : table_(boost::unordered::detail::default_bucket_count, hasher(),
- key_equal(), allocator_type())
+ size_type bucket_count() const BOOST_NOEXCEPT
{
+ return table_.bucket_count_;
}
- 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 key_equal &eql,
- const allocator_type &a)
- : table_(n, hf, eql, a)
+ size_type max_bucket_count() const BOOST_NOEXCEPT
{
+ return table_.max_bucket_count();
}
- 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)
- {
- }
+ size_type bucket_size(size_type) const;
- 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)
+ size_type bucket(const key_type& k) const
{
+ return table_.hash_to_bucket(table_.hash(k));
}
- template <class K, class T, class H, class P, class A>
- unordered_map<K,T,H,P,A>::unordered_map(allocator_type const& a)
- : table_(boost::unordered::detail::default_bucket_count,
- hasher(), key_equal(), a)
+ local_iterator begin(size_type n)
{
+ return local_iterator(table_.begin(n), n, table_.bucket_count_);
}
- template <class K, class T, class H, class P, class A>
- unordered_map<K,T,H,P,A>::unordered_map(
- unordered_map const& other, allocator_type const& a)
- : table_(other.table_, a)
+ const_local_iterator begin(size_type n) const
{
+ return const_local_iterator(table_.begin(n), n, table_.bucket_count_);
}
- 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())
- {
- table_.insert_range(f, l);
- }
+ local_iterator end(size_type) { return local_iterator(); }
- 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())
- {
- 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 key_equal &eql,
- const allocator_type &a)
- : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, 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)
+ const_local_iterator end(size_type) const { return const_local_iterator(); }
+
+ const_local_iterator cbegin(size_type n) const
{
- table_.insert_range(f, l);
+ return const_local_iterator(table_.begin(n), n, table_.bucket_count_);
}
- 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 allocator_type &a)
- : table_(boost::unordered::detail::initial_size(f, l, n),
- hasher(), key_equal(), a)
+ const_local_iterator cend(size_type) const
{
- table_.insert_range(f, l);
+ return const_local_iterator();
}
- template <class K, class T, class H, class P, class A>
- unordered_map<K,T,H,P,A>::~unordered_map() BOOST_NOEXCEPT {}
+ // hash policy
- 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_)
- {
- }
+ float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
- 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())
- {
- }
+ float load_factor() const BOOST_NOEXCEPT;
+ void max_load_factor(float) BOOST_NOEXCEPT;
+ void rehash(size_type);
+ void reserve(size_type);
-#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
+ friend bool operator==
+ <K, T, H, P, A>(unordered_multimap const&, unordered_multimap const&);
+ friend bool operator!=
+ <K, T, H, P, A>(unordered_multimap const&, unordered_multimap const&);
+#endif
+}; // class template unordered_multimap
- 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)
- : table_(
- boost::unordered::detail::initial_size(
- list.begin(), list.end(), n),
- hf, eql, a)
- {
- table_.insert_range(list.begin(), list.end());
- }
+////////////////////////////////////////////////////////////////////////////////
- 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 allocator_type &a)
- : table_(
- boost::unordered::detail::initial_size(
- list.begin(), list.end(), n),
- hf, key_equal(), a)
- {
- table_.insert_range(list.begin(), list.end());
- }
+template <class K, class T, class H, class P, class A>
+unordered_map<K, T, H, P, A>::unordered_map()
+ : table_(boost::unordered::detail::default_bucket_count, hasher(),
+ key_equal(), allocator_type())
+{
+}
- 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)
- {
- table_.insert_range(list.begin(), list.end());
- }
+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 key_equal& eql, const allocator_type& a)
+ : table_(n, hf, eql, a)
+{
+}
- 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());
- return *this;
- }
+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 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)
+{
+}
+
+template <class K, class T, class H, class P, class A>
+unordered_map<K, T, H, P, A>::unordered_map(allocator_type const& a)
+ : table_(boost::unordered::detail::default_bucket_count, hasher(),
+ key_equal(), a)
+{
+}
+
+template <class K, class T, class H, class P, class A>
+unordered_map<K, T, H, P, A>::unordered_map(
+ unordered_map const& other, allocator_type const& a)
+ : table_(other.table_, a)
+{
+}
+
+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())
+{
+ 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 key_equal& eql)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql,
+ allocator_type())
+{
+ 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 key_equal& eql, const allocator_type& a)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, 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)
+{
+ 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 allocator_type& a)
+ : 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
+{
+}
+
+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())
+{
+}
+
+#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)
+ : table_(
+ boost::unordered::detail::initial_size(list.begin(), list.end(), n),
+ hf, eql, a)
+{
+ table_.insert_range(list.begin(), list.end());
+}
+
+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 allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(list.begin(), list.end(), n),
+ hf, key_equal(), a)
+{
+ table_.insert_range(list.begin(), list.end());
+}
+
+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)
+{
+ table_.insert_range(list.begin(), list.end());
+}
+
+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());
+ return *this;
+}
#endif
- // size and capacity
+// size and capacity
- 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();
- }
+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();
+}
- // modifiers
+// modifiers
- 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);
- }
+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 !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- 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());
- }
+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());
+}
#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(const_iterator position)
- {
- return table_.erase(position);
- }
+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);
+}
- 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);
- }
+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);
+}
- 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>
+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();
- }
+template <class K, class T, class H, class P, class A>
+void unordered_map<K, T, H, P, A>::clear()
+{
+ table_.clear();
+}
- template <class K, class T, class H, class P, class A>
- void unordered_map<K,T,H,P,A>::swap(unordered_map& other)
- {
- table_.swap(other.table_);
- }
+template <class K, class T, class H, class P, class A>
+void unordered_map<K, T, H, P, A>::swap(unordered_map& other)
+{
+ table_.swap(other.table_);
+}
- // observers
+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_map<K, T, H2, P2, A>& source)
+{
+ table_.merge_impl(source.table_);
+}
- template <class K, class T, class H, class P, class A>
- typename unordered_map<K,T,H,P,A>::hasher
- unordered_map<K,T,H,P,A>::hash_function() const
- {
- return table_.hash_function();
- }
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+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_map<K, T, H2, P2, A>&& source)
+{
+ table_.merge_impl(source.table_);
+}
+#endif
- template <class K, class T, class H, class P, class A>
- typename unordered_map<K,T,H,P,A>::key_equal
- unordered_map<K,T,H,P,A>::key_eq() const
- {
- return table_.key_eq();
- }
+#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_);
+}
- 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_[k].second;
- }
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+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_);
+}
+#endif
+#endif
- 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;
- }
+// observers
- 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;
- }
+template <class K, class T, class H, class P, class A>
+typename unordered_map<K, T, H, P, A>::hasher
+unordered_map<K, T, H, P, A>::hash_function() const
+{
+ return table_.hash_function();
+}
- // lookup
+template <class K, class T, class H, class P, class A>
+typename unordered_map<K, T, H, P, A>::key_equal
+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>::iterator
- unordered_map<K,T,H,P,A>::find(const key_type& k)
- {
- return iterator(table_.find_node(k));
- }
+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>::const_iterator
- unordered_map<K,T,H,P,A>::find(const key_type& k) const
- {
- return const_iterator(table_.find_node(k));
- }
+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>
- template <class CompatibleKey, class CompatibleHash,
- class CompatiblePredicate>
- 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));
- }
+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;
+}
- template <class K, class T, class H, class P, class A>
- template <class CompatibleKey, class CompatibleHash,
- class CompatiblePredicate>
- 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));
- }
+// lookup
- 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);
- }
+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>::find(const key_type& k)
+{
+ return iterator(table_.find_node(k));
+}
- template <class K, class T, class H, class P, class A>
- 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);
- }
+template <class K, class T, class H, class P, class A>
+typename unordered_map<K, T, H, P, A>::const_iterator
+unordered_map<K, T, H, P, A>::find(const key_type& k) const
+{
+ return const_iterator(table_.find_node(k));
+}
+
+template <class K, class T, class H, class P, class A>
+template <class CompatibleKey, class CompatibleHash, class CompatiblePredicate>
+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));
+}
+
+template <class K, class T, class H, class P, class A>
+template <class CompatibleKey, class CompatibleHash, class CompatiblePredicate>
+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));
+}
- template <class K, class T, class H, class P, class A>
- 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);
- }
+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);
+}
- 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>::bucket_size(size_type n) const
- {
- return table_.bucket_size(n);
- }
+template <class K, class T, class H, class P, class A>
+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);
+}
- // hash policy
+template <class K, class T, class H, class P, class A>
+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);
+}
- 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();
- }
+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>::bucket_size(size_type n) const
+{
+ return table_.bucket_size(n);
+}
- template <class K, class T, class H, class P, class A>
- void unordered_map<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
- {
- table_.max_load_factor(m);
- }
+// hash policy
- template <class K, class T, class H, class P, class A>
- void unordered_map<K,T,H,P,A>::rehash(size_type n)
- {
- table_.rehash(n);
- }
+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();
+}
- 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);
- }
+template <class K, class T, class H, class P, class A>
+void unordered_map<K, T, H, P, A>::max_load_factor(float m) BOOST_NOEXCEPT
+{
+ table_.max_load_factor(m);
+}
- template <class K, class T, class H, class P, class A>
- inline bool operator==(
- unordered_map<K,T,H,P,A> const& m1,
- unordered_map<K,T,H,P,A> const& m2)
- {
+template <class K, class T, class H, class P, class A>
+void unordered_map<K, T, H, P, A>::rehash(size_type n)
+{
+ table_.rehash(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);
+}
+
+template <class K, class T, class H, class P, class A>
+inline bool operator==(unordered_map<K, T, H, P, A> const& m1,
+ unordered_map<K, T, H, P, A> const& m2)
+{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { unordered_map<K,T,H,P,A> x; };
+ struct dummy
+ {
+ unordered_map<K, T, H, P, A> x;
+ };
#endif
- return m1.table_.equals(m2.table_);
- }
+ return m1.table_.equals(m2.table_);
+}
- template <class K, class T, class H, class P, class A>
- inline bool operator!=(
- unordered_map<K,T,H,P,A> const& m1,
- unordered_map<K,T,H,P,A> const& m2)
- {
+template <class K, class T, class H, class P, class A>
+inline bool operator!=(unordered_map<K, T, H, P, A> const& m1,
+ unordered_map<K, T, H, P, A> const& m2)
+{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { unordered_map<K,T,H,P,A> x; };
+ struct dummy
+ {
+ unordered_map<K, T, H, P, A> x;
+ };
#endif
- return !m1.table_.equals(m2.table_);
- }
+ return !m1.table_.equals(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)
- {
+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)
+{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { unordered_map<K,T,H,P,A> x; };
+ struct dummy
+ {
+ unordered_map<K, T, H, P, A> x;
+ };
#endif
- m1.swap(m2);
- }
+ m1.swap(m2);
+}
////////////////////////////////////////////////////////////////////////////////
- template <class K, class T, class H, class P, class A>
- unordered_multimap<K,T,H,P,A>::unordered_multimap()
- : table_(boost::unordered::detail::default_bucket_count, hasher(),
- key_equal(), allocator_type())
- {
- }
+template <class K, class T, class H, class P, class A>
+unordered_multimap<K, T, H, P, A>::unordered_multimap()
+ : table_(boost::unordered::detail::default_bucket_count, hasher(),
+ key_equal(), allocator_type())
+{
+}
- 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 key_equal &eql,
- const allocator_type &a)
- : table_(n, hf, eql, a)
- {
- }
+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 key_equal& eql, const allocator_type& a)
+ : table_(n, hf, eql, a)
+{
+}
- 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 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 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)
- {
- }
+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)
+{
+}
- template <class K, class T, class H, class P, class A>
- unordered_multimap<K,T,H,P,A>::unordered_multimap(allocator_type const& a)
- : table_(boost::unordered::detail::default_bucket_count,
- hasher(), key_equal(), a)
- {
- }
+template <class K, class T, class H, class P, class A>
+unordered_multimap<K, T, H, P, A>::unordered_multimap(allocator_type const& a)
+ : table_(boost::unordered::detail::default_bucket_count, hasher(),
+ key_equal(), a)
+{
+}
- template <class K, class T, class H, class P, class A>
- unordered_multimap<K,T,H,P,A>::unordered_multimap(
- unordered_multimap const& other, allocator_type const& a)
- : table_(other.table_, a)
- {
- }
+template <class K, class T, class H, class P, class A>
+unordered_multimap<K, T, H, P, A>::unordered_multimap(
+ unordered_multimap const& other, allocator_type const& a)
+ : table_(other.table_, a)
+{
+}
- 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())
- {
- 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)
+ : table_(boost::unordered::detail::initial_size(f, l), hasher(),
+ key_equal(), allocator_type())
+{
+ 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, size_type n, const hasher& hf, const key_equal& eql)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql,
+ allocator_type())
+{
+ 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,
+ 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)
+{
+ 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,
+ size_type n, const hasher& hf, const allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(f, l, n), hf, 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, size_type n, const allocator_type& a)
+ : 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>
- 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())
- {
- 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,
- 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)
- {
- 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,
- size_type n,
- const hasher &hf,
- const allocator_type &a)
- : table_(boost::unordered::detail::initial_size(f, l, n),
- hf, key_equal(), a)
- {
- table_.insert_range(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>
- template <class InputIt>
- unordered_multimap<K,T,H,P,A>::unordered_multimap(
- InputIt f, InputIt l,
- size_type n,
- const allocator_type &a)
- : 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_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_NOEXCEPT {}
+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 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_)
- {
- }
+#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(
- BOOST_RV_REF(unordered_multimap) other, allocator_type const& a)
- : table_(other.table_, a, boost::unordered::detail::move_tag())
- {
- }
+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)
+ : table_(
+ boost::unordered::detail::initial_size(list.begin(), list.end(), n),
+ hf, eql, a)
+{
+ table_.insert_range(list.begin(), list.end());
+}
+
+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 allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(list.begin(), list.end(), n),
+ hf, key_equal(), a)
+{
+ table_.insert_range(list.begin(), list.end());
+}
+
+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)
+{
+ 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());
+ return *this;
+}
- 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)
- : table_(
- boost::unordered::detail::initial_size(
- list.begin(), list.end(), n),
- hf, eql, a)
- {
- table_.insert_range(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 hasher &hf, const allocator_type &a)
- : table_(
- boost::unordered::detail::initial_size(
- list.begin(), list.end(), n),
- hf, key_equal(), a)
- {
- table_.insert_range(list.begin(), list.end());
- }
+// size and capacity
- 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)
- {
- table_.insert_range(list.begin(), list.end());
- }
+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();
+}
- 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());
- return *this;
- }
+// modifiers
+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);
+}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+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());
+}
#endif
- // size and capacity
+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);
+}
- 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();
- }
+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);
+}
- // modifiers
+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 first, const_iterator last)
+{
+ return table_.erase_range(first, last);
+}
- 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);
+template <class K, class T, class H, class P, class A>
+void unordered_multimap<K, T, H, P, A>::clear()
+{
+ table_.clear();
+}
+
+template <class K, class T, class H, class P, class A>
+void unordered_multimap<K, T, H, P, A>::swap(unordered_multimap& other)
+{
+ table_.swap(other.table_);
+}
+
+// observers
+
+template <class K, class T, class H, class P, class A>
+typename unordered_multimap<K, T, H, P, A>::hasher
+unordered_multimap<K, T, H, P, A>::hash_function() const
+{
+ return table_.hash_function();
+}
+
+template <class K, class T, class H, class P, class A>
+typename unordered_multimap<K, T, H, P, A>::key_equal
+unordered_multimap<K, T, H, P, A>::key_eq() const
+{
+ return table_.key_eq();
+}
+
+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(
+ boost::unordered_multimap<K, T, H2, P2, A>& source)
+{
+ while (!source.empty()) {
+ insert(source.extract(source.begin()));
}
+}
-#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- 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());
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+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(
+ boost::unordered_multimap<K, T, H2, P2, A>&& source)
+{
+ while (!source.empty()) {
+ insert(source.extract(source.begin()));
}
+}
#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(const_iterator position)
- {
- return table_.erase(position);
+#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(
+ boost::unordered_map<K, T, H2, P2, A>& source)
+{
+ while (!source.empty()) {
+ insert(source.extract(source.begin()));
}
+}
- 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);
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+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(
+ boost::unordered_map<K, T, H2, P2, A>&& source)
+{
+ while (!source.empty()) {
+ insert(source.extract(source.begin()));
}
+}
+#endif
+#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(
- const_iterator first, const_iterator last)
- {
- return table_.erase_range(first, last);
- }
+// lookup
- template <class K, class T, class H, class P, class A>
- void unordered_multimap<K,T,H,P,A>::clear()
- {
- table_.clear();
- }
+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>::find(const key_type& k)
+{
+ return iterator(table_.find_node(k));
+}
- template <class K, class T, class H, class P, class A>
- void unordered_multimap<K,T,H,P,A>::swap(unordered_multimap& other)
- {
- table_.swap(other.table_);
- }
+template <class K, class T, class H, class P, class A>
+typename unordered_multimap<K, T, H, P, A>::const_iterator
+unordered_multimap<K, T, H, P, A>::find(const key_type& k) const
+{
+ return const_iterator(table_.find_node(k));
+}
+
+template <class K, class T, class H, class P, class A>
+template <class CompatibleKey, class CompatibleHash, class CompatiblePredicate>
+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));
+}
+
+template <class K, class T, class H, class P, class A>
+template <class CompatibleKey, class CompatibleHash, class CompatiblePredicate>
+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));
+}
- // observers
+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);
+}
- template <class K, class T, class H, class P, class A>
- typename unordered_multimap<K,T,H,P,A>::hasher
- unordered_multimap<K,T,H,P,A>::hash_function() const
- {
- return table_.hash_function();
- }
+template <class K, class T, class H, class P, class A>
+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);
+}
- template <class K, class T, class H, class P, class A>
- typename unordered_multimap<K,T,H,P,A>::key_equal
- unordered_multimap<K,T,H,P,A>::key_eq() const
- {
- return table_.key_eq();
- }
+template <class K, class T, class H, class P, class A>
+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);
+}
- // lookup
+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>::bucket_size(size_type n) const
+{
+ return table_.bucket_size(n);
+}
+
+// hash policy
+
+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();
+}
+
+template <class K, class T, class H, class P, class A>
+void unordered_multimap<K, T, H, P, A>::max_load_factor(float m) BOOST_NOEXCEPT
+{
+ table_.max_load_factor(m);
+}
+
+template <class K, class T, class H, class P, class A>
+void unordered_multimap<K, T, H, P, A>::rehash(size_type n)
+{
+ table_.rehash(n);
+}
- 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>::find(const key_type& k)
+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);
+}
+
+template <class K, class T, class H, class P, class A>
+inline bool operator==(unordered_multimap<K, T, H, P, A> const& m1,
+ unordered_multimap<K, T, H, P, A> const& m2)
+{
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+ struct dummy
{
- return iterator(table_.find_node(k));
- }
+ unordered_multimap<K, T, H, P, A> x;
+ };
+#endif
+ return m1.table_.equals(m2.table_);
+}
- template <class K, class T, class H, class P, class A>
- typename unordered_multimap<K,T,H,P,A>::const_iterator
- unordered_multimap<K,T,H,P,A>::find(const key_type& k) const
+template <class K, class T, class H, class P, class A>
+inline bool operator!=(unordered_multimap<K, T, H, P, A> const& m1,
+ unordered_multimap<K, T, H, P, A> const& m2)
+{
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+ struct dummy
{
- return const_iterator(table_.find_node(k));
- }
+ unordered_multimap<K, T, H, P, A> x;
+ };
+#endif
+ return !m1.table_.equals(m2.table_);
+}
- template <class K, class T, class H, class P, class A>
- template <class CompatibleKey, class CompatibleHash,
- class CompatiblePredicate>
- 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)
+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)
+{
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+ struct dummy
{
- return iterator(table_.generic_find_node(k, hash, eq));
- }
+ unordered_multimap<K, T, H, P, A> x;
+ };
+#endif
+ m1.swap(m2);
+}
- template <class K, class T, class H, class P, class A>
- template <class CompatibleKey, class CompatibleHash,
- class CompatiblePredicate>
- 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
+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;
+
+ typedef typename boost::unordered::detail::rebind_wrap<A,
+ std::pair<K const, T> >::type value_allocator;
+ typedef boost::unordered::detail::allocator_traits<value_allocator>
+ value_allocator_traits;
+ typedef N node;
+ typedef typename boost::unordered::detail::rebind_wrap<A, node>::type
+ node_allocator;
+ typedef boost::unordered::detail::allocator_traits<node_allocator>
+ node_allocator_traits;
+ typedef typename node_allocator_traits::pointer node_pointer;
+
+ public:
+ typedef K key_type;
+ typedef T mapped_type;
+ typedef A allocator_type;
+
+ private:
+ node_pointer ptr_;
+ bool has_alloc_;
+ boost::unordered::detail::value_base<value_allocator> alloc_;
+
+ public:
+ BOOST_CONSTEXPR node_handle_map() BOOST_NOEXCEPT : ptr_(), has_alloc_(false)
{
- return const_iterator(table_.generic_find_node(k, hash, 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
+ /*BOOST_CONSTEXPR */ node_handle_map(
+ node_pointer ptr, allocator_type const& a)
+ : ptr_(ptr), has_alloc_(false)
{
- return table_.count(k);
+ if (ptr_) {
+ new ((void*)&alloc_) value_allocator(a);
+ has_alloc_ = true;
+ }
}
- template <class K, class T, class H, class P, class A>
- 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)
+ ~node_handle_map()
{
- return table_.equal_range(k);
+ if (has_alloc_ && ptr_) {
+ node_allocator node_alloc(alloc_.value());
+ boost::unordered::detail::node_tmp<node_allocator> tmp(
+ ptr_, node_alloc);
+ }
+ if (has_alloc_) {
+ alloc_.value_ptr()->~value_allocator();
+ }
}
- template <class K, class T, class H, class P, class A>
- 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
+ node_handle_map(BOOST_RV_REF(node_handle_map) n) BOOST_NOEXCEPT
+ : ptr_(n.ptr_),
+ has_alloc_(false)
{
- return table_.equal_range(k);
+ if (n.has_alloc_) {
+ new ((void*)&alloc_) value_allocator(boost::move(n.alloc_.value()));
+ has_alloc_ = true;
+ n.ptr_ = node_pointer();
+ n.alloc_.value_ptr()->~value_allocator();
+ n.has_alloc_ = false;
+ }
}
- 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>::bucket_size(size_type n) const
+ node_handle_map& operator=(BOOST_RV_REF(node_handle_map) n)
{
- return table_.bucket_size(n);
- }
+ BOOST_ASSERT(!has_alloc_ ||
+ value_allocator_traits::
+ propagate_on_container_move_assignment::value ||
+ (n.has_alloc_ && alloc_.value() == n.alloc_.value()));
- // hash policy
+ if (ptr_) {
+ node_allocator node_alloc(alloc_.value());
+ boost::unordered::detail::node_tmp<node_allocator> tmp(
+ ptr_, node_alloc);
+ ptr_ = node_pointer();
+ }
- 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();
- }
+ if (has_alloc_) {
+ alloc_.value_ptr()->~value_allocator();
+ has_alloc_ = false;
+ }
- template <class K, class T, class H, class P, class A>
- void unordered_multimap<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
- {
- table_.max_load_factor(m);
+ if (!has_alloc_ && n.has_alloc_) {
+ move_allocator(n);
+ }
+
+ ptr_ = n.ptr_;
+ n.ptr_ = node_pointer();
+
+ return *this;
}
- template <class K, class T, class H, class P, class A>
- void unordered_multimap<K,T,H,P,A>::rehash(size_type n)
+ key_type& key() const { return const_cast<key_type&>(ptr_->value().first); }
+
+ mapped_type& mapped() const { return ptr_->value().second; }
+
+ allocator_type get_allocator() const { return alloc_.value(); }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ bool operator!() const BOOST_NOEXCEPT { return ptr_ ? 0 : 1; }
+
+ bool empty() const BOOST_NOEXCEPT { return ptr_ ? 0 : 1; }
+
+ void swap(node_handle_map& n) BOOST_NOEXCEPT_IF(
+ value_allocator_traits::propagate_on_container_swap::value
+ /* || value_allocator_traits::is_always_equal::value */)
{
- table_.rehash(n);
+ if (!has_alloc_) {
+ if (n.has_alloc_) {
+ move_allocator(n);
+ }
+ } else if (!n.has_alloc_) {
+ n.move_allocator(*this);
+ } else {
+ swap_impl(n, boost::unordered::detail::integral_constant<bool,
+ value_allocator_traits::
+ propagate_on_container_swap::value>());
+ }
+ boost::swap(ptr_, n.ptr_);
}
- template <class K, class T, class H, class P, class A>
- void unordered_multimap<K,T,H,P,A>::reserve(size_type n)
+ private:
+ void move_allocator(node_handle_map& n)
{
- table_.reserve(n);
+ new ((void*)&alloc_) value_allocator(boost::move(n.alloc_.value()));
+ n.alloc_.value_ptr()->~value_allocator();
+ has_alloc_ = true;
+ n.has_alloc_ = false;
}
- template <class K, class T, class H, class P, class A>
- inline bool operator==(
- unordered_multimap<K,T,H,P,A> const& m1,
- unordered_multimap<K,T,H,P,A> const& m2)
+ void swap_impl(node_handle_map&, boost::unordered::detail::false_type) {}
+
+ void swap_impl(node_handle_map& n, boost::unordered::detail::true_type)
{
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { unordered_multimap<K,T,H,P,A> x; };
-#endif
- return m1.table_.equals(m2.table_);
+ boost::swap(alloc_, n.alloc_);
}
+};
- template <class K, class T, class H, class P, class A>
- inline bool operator!=(
- unordered_multimap<K,T,H,P,A> const& m1,
- unordered_multimap<K,T,H,P,A> const& m2)
+template <class N, class K, class T, class A>
+void swap(node_handle_map<N, K, T, A>& x, node_handle_map<N, K, T, A>& y)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(x.swap(y)))
+{
+ x.swap(y);
+}
+
+template <class N, class K, class T, class A> struct insert_return_type_map
+{
+ private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_map)
+
+ typedef typename boost::unordered::detail::rebind_wrap<A,
+ std::pair<K const, T> >::type value_allocator;
+ typedef N node_;
+
+ public:
+ bool inserted;
+ boost::unordered::iterator_detail::iterator<node_> position;
+ boost::unordered::node_handle_map<N, K, T, A> node;
+
+ insert_return_type_map() : inserted(false), position(), node() {}
+
+ insert_return_type_map(BOOST_RV_REF(insert_return_type_map)
+ x) BOOST_NOEXCEPT : inserted(x.inserted),
+ position(x.position),
+ node(boost::move(x.node))
{
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { unordered_multimap<K,T,H,P,A> x; };
-#endif
- return !m1.table_.equals(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)
+ insert_return_type_map& operator=(BOOST_RV_REF(insert_return_type_map) x)
{
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { unordered_multimap<K,T,H,P,A> x; };
-#endif
- m1.swap(m2);
+ inserted = x.inserted;
+ position = x.position;
+ node = boost::move(x.node);
+ return *this;
}
+};
+template <class N, class K, class T, class A>
+void swap(insert_return_type_map<N, K, T, A>& x,
+ insert_return_type_map<N, K, T, A>& y)
+{
+ boost::swap(x.node, y.node);
+ boost::swap(x.inserted, y.inserted);
+ boost::swap(x.position, y.position);
+}
} // namespace unordered
} // namespace boost
diff --git a/boost/unordered/unordered_map_fwd.hpp b/boost/unordered/unordered_map_fwd.hpp
index 1eb26ce951..12855e92ad 100644
--- a/boost/unordered/unordered_map_fwd.hpp
+++ b/boost/unordered/unordered_map_fwd.hpp
@@ -11,55 +11,51 @@
#pragma once
#endif
-#include <memory>
-#include <functional>
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
+#include <functional>
+#include <memory>
-namespace boost
-{
- namespace unordered
- {
- template <class K,
- class T,
- class H = boost::hash<K>,
- class P = std::equal_to<K>,
- class A = std::allocator<std::pair<const K, T> > >
- class unordered_map;
-
- 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 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>&);
-
- template <class K,
- class T,
- class H = boost::hash<K>,
- class P = std::equal_to<K>,
- class A = std::allocator<std::pair<const K, T> > >
- class unordered_multimap;
-
- 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 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>&);
- }
+namespace boost {
+namespace unordered {
+template <class K, class T, class H = boost::hash<K>,
+ class P = std::equal_to<K>,
+ class A = std::allocator<std::pair<const K, T> > >
+class unordered_map;
+
+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 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>&);
+
+template <class K, class T, class H = boost::hash<K>,
+ class P = std::equal_to<K>,
+ class A = std::allocator<std::pair<const K, T> > >
+class unordered_multimap;
+
+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 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>&);
+
+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;
+}
- using boost::unordered::unordered_map;
- using boost::unordered::unordered_multimap;
- using boost::unordered::swap;
- using boost::unordered::operator==;
- using boost::unordered::operator!=;
+using boost::unordered::unordered_map;
+using boost::unordered::unordered_multimap;
+using boost::unordered::swap;
+using boost::unordered::operator==;
+using boost::unordered::operator!=;
}
#endif
diff --git a/boost/unordered/unordered_set.hpp b/boost/unordered/unordered_set.hpp
index 77cd87e0fd..40d566c254 100644
--- a/boost/unordered/unordered_set.hpp
+++ b/boost/unordered/unordered_set.hpp
@@ -14,9 +14,10 @@
#pragma once
#endif
-#include <boost/unordered/detail/set.hpp>
+#include <boost/core/explicit_operator_bool.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
+#include <boost/unordered/detail/set.hpp>
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
#include <initializer_list>
@@ -25,1714 +26,1861 @@
#if defined(BOOST_MSVC)
#pragma warning(push)
#if BOOST_MSVC >= 1400
-#pragma warning(disable:4396) //the inline specifier cannot be used when a
- // friend declaration refers to a specialization
- // of a function template
+#pragma warning(disable : 4396) // the inline specifier cannot be used when a
+// friend declaration refers to a specialization
+// of a function template
#endif
#endif
-namespace boost
-{
-namespace unordered
+namespace boost {
+namespace unordered {
+template <class T, class H, class P, class A> class unordered_set
{
- template <class T, class H, class P, class A>
- class unordered_set
- {
#if defined(BOOST_UNORDERED_USE_MOVE)
- BOOST_COPYABLE_AND_MOVABLE(unordered_set)
+ BOOST_COPYABLE_AND_MOVABLE(unordered_set)
#endif
- public:
-
- typedef T key_type;
- typedef T value_type;
- typedef H hasher;
- typedef P key_equal;
- typedef A allocator_type;
+ template <typename, typename, typename, typename>
+ friend class unordered_multiset;
- private:
+ public:
+ typedef T key_type;
+ typedef T value_type;
+ typedef H hasher;
+ typedef P key_equal;
+ typedef A allocator_type;
- typedef boost::unordered::detail::set<A, T, H, P> types;
- typedef typename types::traits allocator_traits;
- typedef typename types::table table;
+ private:
+ typedef boost::unordered::detail::set<A, T, H, P> types;
+ typedef typename types::value_allocator_traits value_allocator_traits;
+ typedef typename types::table table;
- public:
+ public:
+ typedef typename value_allocator_traits::pointer pointer;
+ typedef typename value_allocator_traits::const_pointer const_pointer;
- typedef typename allocator_traits::pointer pointer;
- typedef typename allocator_traits::const_pointer const_pointer;
+ typedef value_type& reference;
+ typedef value_type const& const_reference;
- typedef value_type& reference;
- typedef value_type const& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
- 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 types::node_type node_type;
+ typedef typename types::insert_return_type insert_return_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;
+ private:
+ table table_;
- private:
+ public:
+ // constructors
- table table_;
+ unordered_set();
- public:
+ explicit unordered_set(size_type, const hasher& = hasher(),
+ const key_equal& = key_equal(),
+ const allocator_type& = allocator_type());
- // constructors
+ explicit unordered_set(size_type, const allocator_type&);
- unordered_set();
+ explicit unordered_set(size_type, const hasher&, const allocator_type&);
- explicit unordered_set(
- size_type,
- const hasher& = hasher(),
- const key_equal& = key_equal(),
- const allocator_type& = allocator_type());
+ explicit unordered_set(allocator_type const&);
- explicit unordered_set(
- size_type,
- const allocator_type&);
+ template <class InputIt> unordered_set(InputIt, InputIt);
- 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& = 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 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 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 allocator_type&);
- // copy/move constructors
+ // copy/move constructors
- unordered_set(unordered_set const&);
+ unordered_set(unordered_set const&);
- unordered_set(unordered_set const&, allocator_type const&);
- unordered_set(BOOST_RV_REF(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_UNORDERED_USE_MOVE)
- unordered_set(BOOST_RV_REF(unordered_set) other)
- BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
- : table_(other.table_, boost::unordered::detail::move_tag())
- {
- }
+ 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())
- {
- }
+ unordered_set(unordered_set&& other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
+ : table_(other.table_, boost::unordered::detail::move_tag())
+ {
+ }
#endif
#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&);
- unordered_set(
- std::initializer_list<value_type>,
- size_type,
- const allocator_type&);
+ 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&);
+ unordered_set(
+ std::initializer_list<value_type>, size_type, const allocator_type&);
#endif
- // Destructor
+ // Destructor
- ~unordered_set() BOOST_NOEXCEPT;
+ ~unordered_set() BOOST_NOEXCEPT;
- // Assign
+// Assign
#if defined(BOOST_UNORDERED_USE_MOVE)
- unordered_set& operator=(BOOST_COPY_ASSIGN_REF(unordered_set) x)
- {
- table_.assign(x.table_);
- return *this;
- }
+ unordered_set& operator=(BOOST_COPY_ASSIGN_REF(unordered_set) x)
+ {
+ table_.assign(x.table_);
+ return *this;
+ }
- unordered_set& operator=(BOOST_RV_REF(unordered_set) x)
- {
- table_.move_assign(x.table_);
- return *this;
- }
+ unordered_set& operator=(BOOST_RV_REF(unordered_set) x)
+ {
+ table_.move_assign(x.table_);
+ return *this;
+ }
#else
- unordered_set& operator=(unordered_set const& x)
- {
- table_.assign(x.table_);
- return *this;
- }
+ unordered_set& operator=(unordered_set const& x)
+ {
+ table_.assign(x.table_);
+ return *this;
+ }
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- unordered_set& operator=(unordered_set&& x)
- {
- table_.move_assign(x.table_);
- return *this;
- }
+ unordered_set& operator=(unordered_set&& x)
+ {
+ table_.move_assign(x.table_);
+ return *this;
+ }
#endif
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- unordered_set& operator=(std::initializer_list<value_type>);
+ unordered_set& operator=(std::initializer_list<value_type>);
#endif
- allocator_type get_allocator() const BOOST_NOEXCEPT
- {
- return table_.node_alloc();
- }
+ allocator_type get_allocator() const BOOST_NOEXCEPT
+ {
+ return table_.node_alloc();
+ }
- // size and capacity
+ // size and capacity
- bool empty() const BOOST_NOEXCEPT
- {
- return table_.size_ == 0;
- }
+ bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
- size_type size() const BOOST_NOEXCEPT
- {
- return table_.size_;
- }
+ size_type size() const BOOST_NOEXCEPT { return table_.size_; }
- size_type max_size() const BOOST_NOEXCEPT;
+ size_type max_size() const BOOST_NOEXCEPT;
- // iterators
+ // iterators
- iterator begin() BOOST_NOEXCEPT
- {
- return iterator(table_.begin());
- }
+ iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); }
- const_iterator begin() const BOOST_NOEXCEPT
- {
- return const_iterator(table_.begin());
- }
+ const_iterator begin() const BOOST_NOEXCEPT
+ {
+ return const_iterator(table_.begin());
+ }
- iterator end() BOOST_NOEXCEPT
- {
- return iterator();
- }
+ iterator end() BOOST_NOEXCEPT { return iterator(); }
- const_iterator end() const BOOST_NOEXCEPT
- {
- return const_iterator();
- }
+ const_iterator end() const BOOST_NOEXCEPT { return const_iterator(); }
- const_iterator cbegin() const BOOST_NOEXCEPT
- {
- return const_iterator(table_.begin());
- }
+ const_iterator cbegin() const BOOST_NOEXCEPT
+ {
+ return const_iterator(table_.begin());
+ }
- const_iterator cend() const BOOST_NOEXCEPT
- {
- return const_iterator();
- }
+ const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
+
+ // extract
+
+ node_type extract(const_iterator position)
+ {
+ return node_type(
+ table_.extract_by_iterator(position), table_.node_alloc());
+ }
+
+ node_type extract(const key_type& k)
+ {
+ return node_type(table_.extract_by_key(k), table_.node_alloc());
+ }
- // emplace
+// 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)...);
- }
+ template <class... Args>
+ std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
+ {
+ return table_.emplace(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)...);
- }
+ 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))
- // 0 argument emplace requires special treatment in case
- // the container is instantiated with a value type that
- // doesn't have a default constructor.
+ // 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 this->emplace(boost::move(v));
- }
+ std::pair<iterator, bool> emplace(
+ boost::unordered::detail::empty_emplace =
+ boost::unordered::detail::empty_emplace(),
+ value_type v = value_type())
+ {
+ return this->emplace(boost::move(v));
+ }
- iterator emplace_hint(const_iterator hint,
- boost::unordered::detail::empty_emplace
- = boost::unordered::detail::empty_emplace(),
- value_type v = value_type()
- )
- {
- 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())
+ {
+ return this->emplace_hint(hint, boost::move(v));
+ }
#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>
+ 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>
+ 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))
- );
- }
+ 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)));
+ }
- 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>
+ 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))
- );
- }
+ 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)));
+ }
- 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))
- );
- }
+ 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)));
+ }
-#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_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))); \
+ }
- BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_EMPLACE, _)
+ BOOST_PP_REPEAT_FROM_TO(
+ 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE
#endif
- std::pair<iterator, bool> insert(value_type const& x)
- {
- return this->emplace(x);
- }
+ std::pair<iterator, bool> insert(value_type const& x)
+ {
+ return this->emplace(x);
+ }
- std::pair<iterator, bool> insert(BOOST_UNORDERED_RV_REF(value_type) x)
- {
- return this->emplace(boost::move(x));
- }
+ std::pair<iterator, bool> insert(BOOST_UNORDERED_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, value_type const& x)
+ {
+ return this->emplace_hint(hint, x);
+ }
- iterator insert(const_iterator hint,
- BOOST_UNORDERED_RV_REF(value_type) x)
- {
- return this->emplace_hint(hint, boost::move(x));
- }
+ iterator insert(const_iterator hint, BOOST_UNORDERED_RV_REF(value_type) x)
+ {
+ return this->emplace_hint(hint, boost::move(x));
+ }
- template <class InputIt> void insert(InputIt, InputIt);
+ template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- void insert(std::initializer_list<value_type>);
+ void insert(std::initializer_list<value_type>);
#endif
- iterator erase(const_iterator);
- size_type erase(const key_type&);
- iterator erase(const_iterator, const_iterator);
- void quick_erase(const_iterator it) { erase(it); }
- void erase_return_void(const_iterator it) { erase(it); }
+ 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);
+ }
- void clear();
- void swap(unordered_set&);
+ iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
+ {
+ return table_.move_insert_node_type_with_hint(hint, np);
+ }
- // observers
+#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);
- hasher hash_function() const;
- key_equal key_eq() const;
+ public:
+#endif
- // lookup
+ iterator erase(const_iterator);
+ size_type erase(const key_type&);
+ iterator erase(const_iterator, const_iterator);
+ void quick_erase(const_iterator it) { erase(it); }
+ void erase_return_void(const_iterator it) { erase(it); }
- const_iterator find(const key_type&) const;
+ void clear();
+ void swap(unordered_set&);
- template <class CompatibleKey, class CompatibleHash,
- class CompatiblePredicate>
- const_iterator find(
- CompatibleKey const&,
- CompatibleHash const&,
- CompatiblePredicate const&) const;
+ template <typename H2, typename P2>
+ void merge(boost::unordered_set<T, H2, P2, A>& source);
- size_type count(const key_type&) const;
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename H2, typename P2>
+ void merge(boost::unordered_set<T, H2, P2, A>&& source);
+#endif
- std::pair<const_iterator, const_iterator>
- equal_range(const key_type&) const;
+#if BOOST_UNORDERED_INTEROPERABLE_NODES
+ template <typename H2, typename P2>
+ void merge(boost::unordered_multiset<T, H2, P2, A>& source);
- // bucket interface
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename H2, typename P2>
+ void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
+#endif
+#endif
- size_type bucket_count() const BOOST_NOEXCEPT
- {
- return table_.bucket_count_;
- }
+ // observers
- size_type max_bucket_count() const BOOST_NOEXCEPT
- {
- return table_.max_bucket_count();
- }
+ hasher hash_function() const;
+ key_equal key_eq() const;
- size_type bucket_size(size_type) const;
+ // lookup
- size_type bucket(const key_type& k) const
- {
- return table_.hash_to_bucket(table_.hash(k));
- }
+ const_iterator find(const key_type&) const;
- local_iterator begin(size_type n)
- {
- return local_iterator(
- table_.begin(n), n, table_.bucket_count_);
- }
+ template <class CompatibleKey, class CompatibleHash,
+ class CompatiblePredicate>
+ const_iterator find(CompatibleKey const&, CompatibleHash const&,
+ CompatiblePredicate const&) const;
- const_local_iterator begin(size_type n) const
- {
- return const_local_iterator(
- table_.begin(n), n, table_.bucket_count_);
- }
+ size_type count(const key_type&) const;
- local_iterator end(size_type)
- {
- return local_iterator();
- }
+ std::pair<const_iterator, const_iterator> equal_range(
+ const key_type&) const;
- const_local_iterator end(size_type) const
- {
- return const_local_iterator();
- }
+ // bucket interface
- const_local_iterator cbegin(size_type n) const
- {
- return const_local_iterator(
- table_.begin(n), n, table_.bucket_count_);
- }
+ size_type bucket_count() const BOOST_NOEXCEPT
+ {
+ return table_.bucket_count_;
+ }
- const_local_iterator cend(size_type) const
- {
- return const_local_iterator();
- }
+ size_type max_bucket_count() const BOOST_NOEXCEPT
+ {
+ return table_.max_bucket_count();
+ }
- // hash policy
+ size_type bucket_size(size_type) const;
- float max_load_factor() const BOOST_NOEXCEPT
- {
- return table_.mlf_;
- }
+ size_type bucket(const key_type& k) const
+ {
+ return table_.hash_to_bucket(table_.hash(k));
+ }
- float load_factor() const BOOST_NOEXCEPT;
- void max_load_factor(float) BOOST_NOEXCEPT;
- void rehash(size_type);
- void reserve(size_type);
+ local_iterator begin(size_type n)
+ {
+ return local_iterator(table_.begin(n), n, table_.bucket_count_);
+ }
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
- friend bool operator==<T,H,P,A>(
- unordered_set const&, unordered_set const&);
- friend bool operator!=<T,H,P,A>(
- unordered_set const&, unordered_set const&);
-#endif
- }; // class template unordered_set
+ const_local_iterator begin(size_type n) const
+ {
+ return const_local_iterator(table_.begin(n), n, table_.bucket_count_);
+ }
+
+ local_iterator end(size_type) { return local_iterator(); }
- template <class T, class H, class P, class A>
- class unordered_multiset
+ const_local_iterator end(size_type) const { return const_local_iterator(); }
+
+ const_local_iterator cbegin(size_type n) const
{
-#if defined(BOOST_UNORDERED_USE_MOVE)
- BOOST_COPYABLE_AND_MOVABLE(unordered_multiset)
-#endif
- public:
+ return const_local_iterator(table_.begin(n), n, table_.bucket_count_);
+ }
- typedef T key_type;
- typedef T value_type;
- typedef H hasher;
- typedef P key_equal;
- typedef A allocator_type;
+ const_local_iterator cend(size_type) const
+ {
+ return const_local_iterator();
+ }
- private:
+ // hash policy
- typedef boost::unordered::detail::multiset<A, T, H, P> types;
- typedef typename types::traits allocator_traits;
- typedef typename types::table table;
+ float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
- public:
+ float load_factor() const BOOST_NOEXCEPT;
+ void max_load_factor(float) BOOST_NOEXCEPT;
+ void rehash(size_type);
+ void reserve(size_type);
- typedef typename allocator_traits::pointer pointer;
- typedef typename allocator_traits::const_pointer const_pointer;
+#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
+ friend bool operator==
+ <T, H, P, A>(unordered_set const&, unordered_set const&);
+ friend bool operator!=
+ <T, H, P, A>(unordered_set const&, unordered_set const&);
+#endif
+}; // class template unordered_set
- typedef value_type& reference;
- typedef value_type const& const_reference;
+template <class T, class H, class P, class A> class unordered_multiset
+{
+#if defined(BOOST_UNORDERED_USE_MOVE)
+ BOOST_COPYABLE_AND_MOVABLE(unordered_multiset)
+#endif
+ template <typename, typename, typename, typename>
+ friend class unordered_set;
+
+ public:
+ typedef T key_type;
+ typedef T value_type;
+ typedef H hasher;
+ typedef P key_equal;
+ typedef A allocator_type;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
+ private:
+ typedef boost::unordered::detail::multiset<A, T, H, P> types;
+ typedef typename types::value_allocator_traits value_allocator_traits;
+ typedef typename types::table table;
- 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;
+ public:
+ typedef typename value_allocator_traits::pointer pointer;
+ typedef typename value_allocator_traits::const_pointer const_pointer;
- private:
+ typedef value_type& reference;
+ typedef value_type const& const_reference;
- table table_;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
- public:
+ 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 types::node_type node_type;
- // constructors
+ private:
+ table table_;
- unordered_multiset();
+ public:
+ // constructors
- explicit unordered_multiset(
- size_type,
- const hasher& = hasher(),
- const key_equal& = key_equal(),
- const allocator_type& = allocator_type());
+ unordered_multiset();
- explicit unordered_multiset(
- size_type,
- const allocator_type&);
+ explicit unordered_multiset(size_type, const hasher& = hasher(),
+ const key_equal& = key_equal(),
+ const allocator_type& = allocator_type());
- explicit unordered_multiset(
- size_type,
- const hasher&,
- const allocator_type&);
+ explicit unordered_multiset(size_type, const allocator_type&);
- explicit unordered_multiset(allocator_type const&);
+ explicit unordered_multiset(
+ size_type, const hasher&, const allocator_type&);
- template <class InputIt>
- unordered_multiset(InputIt, InputIt);
+ explicit unordered_multiset(allocator_type const&);
- template <class InputIt>
- unordered_multiset(
- InputIt, InputIt,
- size_type,
- const hasher& = hasher(),
- const key_equal& = key_equal());
+ template <class InputIt> unordered_multiset(InputIt, InputIt);
- 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& = 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 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 allocator_type&);
- // copy/move constructors
+ // copy/move constructors
- unordered_multiset(unordered_multiset const&);
+ unordered_multiset(unordered_multiset const&);
- unordered_multiset(unordered_multiset const&, allocator_type const&);
- unordered_multiset(BOOST_RV_REF(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_UNORDERED_USE_MOVE)
- unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
- BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
- : table_(other.table_, boost::unordered::detail::move_tag())
- {
- }
+ 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())
- {
- }
+ unordered_multiset(unordered_multiset&& other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
+ : table_(other.table_, boost::unordered::detail::move_tag())
+ {
+ }
#endif
#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&);
- unordered_multiset(
- std::initializer_list<value_type>,
- size_type,
- const allocator_type&);
+ 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&);
+ unordered_multiset(
+ std::initializer_list<value_type>, size_type, const allocator_type&);
#endif
- // Destructor
+ // Destructor
- ~unordered_multiset() BOOST_NOEXCEPT;
+ ~unordered_multiset() BOOST_NOEXCEPT;
- // Assign
+// Assign
#if defined(BOOST_UNORDERED_USE_MOVE)
- unordered_multiset& operator=(
- BOOST_COPY_ASSIGN_REF(unordered_multiset) x)
- {
- table_.assign(x.table_);
- return *this;
- }
+ unordered_multiset& operator=(BOOST_COPY_ASSIGN_REF(unordered_multiset) x)
+ {
+ table_.assign(x.table_);
+ return *this;
+ }
- unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x)
- {
- table_.move_assign(x.table_);
- return *this;
- }
+ unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x)
+ {
+ table_.move_assign(x.table_);
+ return *this;
+ }
#else
- unordered_multiset& operator=(unordered_multiset const& x)
- {
- table_.assign(x.table_);
- return *this;
- }
+ unordered_multiset& operator=(unordered_multiset const& x)
+ {
+ table_.assign(x.table_);
+ return *this;
+ }
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- unordered_multiset& operator=(unordered_multiset&& x)
- {
- table_.move_assign(x.table_);
- return *this;
- }
+ unordered_multiset& operator=(unordered_multiset&& x)
+ {
+ table_.move_assign(x.table_);
+ return *this;
+ }
#endif
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- unordered_multiset& operator=(std::initializer_list<value_type>);
+ unordered_multiset& operator=(std::initializer_list<value_type>);
#endif
- allocator_type get_allocator() const BOOST_NOEXCEPT
- {
- return table_.node_alloc();
- }
+ allocator_type get_allocator() const BOOST_NOEXCEPT
+ {
+ return table_.node_alloc();
+ }
- // size and capacity
+ // size and capacity
- bool empty() const BOOST_NOEXCEPT
- {
- return table_.size_ == 0;
- }
+ bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; }
- size_type size() const BOOST_NOEXCEPT
- {
- return table_.size_;
- }
+ size_type size() const BOOST_NOEXCEPT { return table_.size_; }
- size_type max_size() const BOOST_NOEXCEPT;
+ size_type max_size() const BOOST_NOEXCEPT;
- // iterators
+ // iterators
- iterator begin() BOOST_NOEXCEPT
- {
- return iterator(table_.begin());
- }
+ iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); }
- const_iterator begin() const BOOST_NOEXCEPT
- {
- return const_iterator(table_.begin());
- }
+ const_iterator begin() const BOOST_NOEXCEPT
+ {
+ return const_iterator(table_.begin());
+ }
- iterator end() BOOST_NOEXCEPT
- {
- return iterator();
- }
+ iterator end() BOOST_NOEXCEPT { return iterator(); }
- const_iterator end() const BOOST_NOEXCEPT
- {
- return const_iterator();
- }
+ const_iterator end() const BOOST_NOEXCEPT { return const_iterator(); }
- const_iterator cbegin() const BOOST_NOEXCEPT
- {
- return const_iterator(table_.begin());
- }
+ const_iterator cbegin() const BOOST_NOEXCEPT
+ {
+ return const_iterator(table_.begin());
+ }
- const_iterator cend() const BOOST_NOEXCEPT
- {
- return const_iterator();
- }
+ const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
- // emplace
+ // extract
+
+ node_type extract(const_iterator position)
+ {
+ return node_type(
+ table_.extract_by_iterator(position), table_.node_alloc());
+ }
+
+ node_type extract(const key_type& k)
+ {
+ return node_type(table_.extract_by_key(k), table_.node_alloc());
+ }
+
+// 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)...);
- }
+ template <class... Args> iterator emplace(BOOST_FWD_REF(Args)... args)
+ {
+ return table_.emplace(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)...);
- }
+ 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))
- // 0 argument emplace requires special treatment in case
- // the container is instantiated with a value type that
- // doesn't have a default constructor.
+ // 0 argument emplace requires special treatment in case
+ // the container is instantiated with a value type that
+ // doesn't have a default constructor.
- iterator emplace(
- boost::unordered::detail::empty_emplace
- = boost::unordered::detail::empty_emplace(),
- value_type v = value_type())
- {
- return this->emplace(boost::move(v));
- }
+ iterator emplace(boost::unordered::detail::empty_emplace =
+ boost::unordered::detail::empty_emplace(),
+ value_type v = value_type())
+ {
+ return this->emplace(boost::move(v));
+ }
- iterator emplace_hint(const_iterator hint,
- boost::unordered::detail::empty_emplace
- = boost::unordered::detail::empty_emplace(),
- value_type v = value_type()
- )
- {
- 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())
+ {
+ return this->emplace_hint(hint, boost::move(v));
+ }
#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(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>
+ 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))
- );
- }
+ 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)));
+ }
- 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>
+ 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))
- );
- }
+ 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)));
+ }
- 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))
- );
- }
+ 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)));
+ }
-#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) \
- )); \
- } \
- \
- 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_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))); \
+ } \
+ \
+ 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, _)
+ BOOST_PP_REPEAT_FROM_TO(
+ 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EMPLACE, _)
#undef BOOST_UNORDERED_EMPLACE
#endif
- iterator insert(value_type const& x)
- {
- return this->emplace(x);
- }
+ iterator insert(value_type const& x) { return this->emplace(x); }
- iterator insert(BOOST_UNORDERED_RV_REF(value_type) x)
- {
- return this->emplace(boost::move(x));
- }
+ iterator insert(BOOST_UNORDERED_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, value_type const& x)
+ {
+ return this->emplace_hint(hint, x);
+ }
- iterator insert(const_iterator hint,
- BOOST_UNORDERED_RV_REF(value_type) x)
- {
- return this->emplace_hint(hint, boost::move(x));
- }
+ iterator insert(const_iterator hint, BOOST_UNORDERED_RV_REF(value_type) x)
+ {
+ return this->emplace_hint(hint, boost::move(x));
+ }
- template <class InputIt> void insert(InputIt, InputIt);
+ template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- void insert(std::initializer_list<value_type>);
+ void insert(std::initializer_list<value_type>);
#endif
- iterator erase(const_iterator);
- size_type erase(const key_type&);
- iterator erase(const_iterator, const_iterator);
- void quick_erase(const_iterator it) { erase(it); }
- void erase_return_void(const_iterator it) { erase(it); }
-
- void clear();
- void swap(unordered_multiset&);
-
- // observers
-
- hasher hash_function() const;
- key_equal key_eq() const;
-
- // lookup
-
- const_iterator find(const key_type&) const;
-
- template <class CompatibleKey, class CompatibleHash,
- class CompatiblePredicate>
- const_iterator find(
- CompatibleKey const&,
- CompatibleHash const&,
- CompatiblePredicate const&) const;
-
- size_type count(const key_type&) const;
+ iterator insert(BOOST_RV_REF(node_type) np)
+ {
+ return table_.move_insert_node_type(np);
+ }
- std::pair<const_iterator, const_iterator>
- equal_range(const key_type&) const;
+ iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
+ {
+ return table_.move_insert_node_type_with_hint(hint, np);
+ }
- // bucket interface
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ private:
+ // Note: Use r-value node_type to insert.
+ iterator insert(node_type&);
+ iterator insert(const_iterator, node_type& np);
- size_type bucket_count() const BOOST_NOEXCEPT
- {
- return table_.bucket_count_;
- }
+ public:
+#endif
- size_type max_bucket_count() const BOOST_NOEXCEPT
- {
- return table_.max_bucket_count();
- }
+ iterator erase(const_iterator);
+ size_type erase(const key_type&);
+ iterator erase(const_iterator, const_iterator);
+ void quick_erase(const_iterator it) { erase(it); }
+ void erase_return_void(const_iterator it) { erase(it); }
- size_type bucket_size(size_type) const;
+ void clear();
+ void swap(unordered_multiset&);
- size_type bucket(const key_type& k) const
- {
- return table_.hash_to_bucket(table_.hash(k));
- }
+ template <typename H2, typename P2>
+ void merge(boost::unordered_multiset<T, H2, P2, A>& source);
- local_iterator begin(size_type n)
- {
- return local_iterator(
- table_.begin(n), n, table_.bucket_count_);
- }
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename H2, typename P2>
+ void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
+#endif
- const_local_iterator begin(size_type n) const
- {
- return const_local_iterator(
- table_.begin(n), n, table_.bucket_count_);
- }
+#if BOOST_UNORDERED_INTEROPERABLE_NODES
+ template <typename H2, typename P2>
+ void merge(boost::unordered_set<T, H2, P2, A>& source);
- local_iterator end(size_type)
- {
- return local_iterator();
- }
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename H2, typename P2>
+ void merge(boost::unordered_set<T, H2, P2, A>&& source);
+#endif
+#endif
- const_local_iterator end(size_type) const
- {
- return const_local_iterator();
- }
+ // observers
- const_local_iterator cbegin(size_type n) const
- {
- return const_local_iterator(
- table_.begin(n), n, table_.bucket_count_);
- }
+ hasher hash_function() const;
+ key_equal key_eq() const;
- const_local_iterator cend(size_type) const
- {
- return const_local_iterator();
- }
+ // lookup
- // hash policy
+ const_iterator find(const key_type&) const;
- float max_load_factor() const BOOST_NOEXCEPT
- {
- return table_.mlf_;
- }
+ template <class CompatibleKey, class CompatibleHash,
+ class CompatiblePredicate>
+ const_iterator find(CompatibleKey const&, CompatibleHash const&,
+ CompatiblePredicate const&) const;
- float load_factor() const BOOST_NOEXCEPT;
- void max_load_factor(float) BOOST_NOEXCEPT;
- void rehash(size_type);
- void reserve(size_type);
+ size_type count(const key_type&) const;
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
- friend bool operator==<T,H,P,A>(
- unordered_multiset const&, unordered_multiset const&);
- friend bool operator!=<T,H,P,A>(
- unordered_multiset const&, unordered_multiset const&);
-#endif
- }; // class template unordered_multiset
+ std::pair<const_iterator, const_iterator> equal_range(
+ const key_type&) const;
-////////////////////////////////////////////////////////////////////////////////
+ // bucket interface
- 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(),
- key_equal(), allocator_type())
+ size_type bucket_count() const BOOST_NOEXCEPT
{
+ return table_.bucket_count_;
}
- template <class T, class H, class P, class A>
- unordered_set<T,H,P,A>::unordered_set(
- size_type n, const hasher &hf, const key_equal &eql,
- const allocator_type &a)
- : table_(n, hf, eql, a)
+ size_type max_bucket_count() const BOOST_NOEXCEPT
{
+ return table_.max_bucket_count();
}
- 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)
- {
- }
+ size_type bucket_size(size_type) const;
- 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)
+ size_type bucket(const key_type& k) const
{
+ return table_.hash_to_bucket(table_.hash(k));
}
- template <class T, class H, class P, class A>
- unordered_set<T,H,P,A>::unordered_set(allocator_type const& a)
- : table_(boost::unordered::detail::default_bucket_count,
- hasher(), key_equal(), a)
+ local_iterator begin(size_type n)
{
+ return local_iterator(table_.begin(n), n, table_.bucket_count_);
}
- template <class T, class H, class P, class A>
- unordered_set<T,H,P,A>::unordered_set(
- unordered_set const& other, allocator_type const& a)
- : table_(other.table_, a)
+ const_local_iterator begin(size_type n) const
{
+ return const_local_iterator(table_.begin(n), n, table_.bucket_count_);
}
- 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())
- {
- table_.insert_range(f, l);
- }
+ local_iterator end(size_type) { return local_iterator(); }
- 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())
- {
- 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 key_equal &eql,
- const allocator_type &a)
- : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, 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)
+ const_local_iterator end(size_type) const { return const_local_iterator(); }
+
+ const_local_iterator cbegin(size_type n) const
{
- table_.insert_range(f, l);
+ return const_local_iterator(table_.begin(n), n, table_.bucket_count_);
}
- 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 allocator_type &a)
- : table_(boost::unordered::detail::initial_size(f, l, n),
- hasher(), key_equal(), a)
+ const_local_iterator cend(size_type) const
{
- table_.insert_range(f, l);
+ return const_local_iterator();
}
- template <class T, class H, class P, class A>
- unordered_set<T,H,P,A>::~unordered_set() BOOST_NOEXCEPT {}
+ // hash policy
- template <class T, class H, class P, class A>
- unordered_set<T,H,P,A>::unordered_set(
- unordered_set const& other)
- : table_(other.table_)
- {
- }
+ float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; }
- 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())
- {
- }
+ float load_factor() const BOOST_NOEXCEPT;
+ void max_load_factor(float) BOOST_NOEXCEPT;
+ void rehash(size_type);
+ void reserve(size_type);
-#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
+ friend bool operator==
+ <T, H, P, A>(unordered_multiset const&, unordered_multiset const&);
+ friend bool operator!=
+ <T, H, P, A>(unordered_multiset const&, unordered_multiset const&);
+#endif
+}; // class template unordered_multiset
- 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)
- : table_(
- boost::unordered::detail::initial_size(
- list.begin(), list.end(), n),
- hf, eql, a)
- {
- table_.insert_range(list.begin(), list.end());
- }
+////////////////////////////////////////////////////////////////////////////////
- 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 allocator_type &a)
- : table_(
- boost::unordered::detail::initial_size(
- list.begin(), list.end(), n),
- hf, key_equal(), a)
- {
- table_.insert_range(list.begin(), list.end());
- }
+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(),
+ key_equal(), allocator_type())
+{
+}
- 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)
- {
- table_.insert_range(list.begin(), list.end());
- }
+template <class T, class H, class P, class A>
+unordered_set<T, H, P, A>::unordered_set(size_type n, const hasher& hf,
+ const key_equal& eql, const allocator_type& a)
+ : table_(n, hf, eql, a)
+{
+}
- 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());
- return *this;
- }
+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 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)
+{
+}
+
+template <class T, class H, class P, class A>
+unordered_set<T, H, P, A>::unordered_set(allocator_type const& a)
+ : table_(boost::unordered::detail::default_bucket_count, hasher(),
+ key_equal(), a)
+{
+}
+
+template <class T, class H, class P, class A>
+unordered_set<T, H, P, A>::unordered_set(
+ unordered_set const& other, allocator_type const& a)
+ : table_(other.table_, a)
+{
+}
+
+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())
+{
+ 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 key_equal& eql)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql,
+ allocator_type())
+{
+ 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 key_equal& eql, const allocator_type& a)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, 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)
+{
+ 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 allocator_type& a)
+ : 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_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())
+{
+}
+
+#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)
+ : table_(
+ boost::unordered::detail::initial_size(list.begin(), list.end(), n),
+ hf, eql, a)
+{
+ table_.insert_range(list.begin(), list.end());
+}
+
+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 allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(list.begin(), list.end(), n),
+ hf, key_equal(), a)
+{
+ table_.insert_range(list.begin(), list.end());
+}
+
+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)
+{
+ table_.insert_range(list.begin(), list.end());
+}
+
+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());
+ return *this;
+}
#endif
- // size and capacity
+// size and capacity
- 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();
- }
+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();
+}
- // modifiers
+// modifiers
- 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);
- }
+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 !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());
- }
+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());
+}
#endif
- 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);
- }
+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);
+}
- 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);
- }
+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);
+}
- 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>
+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();
- }
+template <class T, class H, class P, class A>
+void unordered_set<T, H, P, A>::clear()
+{
+ table_.clear();
+}
- template <class T, class H, class P, class A>
- void unordered_set<T,H,P,A>::swap(unordered_set& other)
- {
- table_.swap(other.table_);
- }
+template <class T, class H, class P, class A>
+void unordered_set<T, H, P, A>::swap(unordered_set& other)
+{
+ table_.swap(other.table_);
+}
- // observers
+// observers
- template <class T, class H, class P, class A>
- typename unordered_set<T,H,P,A>::hasher
- unordered_set<T,H,P,A>::hash_function() const
- {
- return table_.hash_function();
- }
+template <class T, class H, class P, class A>
+typename unordered_set<T, H, P, A>::hasher
+unordered_set<T, H, P, A>::hash_function() const
+{
+ return table_.hash_function();
+}
- template <class T, class H, class P, class A>
- typename unordered_set<T,H,P,A>::key_equal
- unordered_set<T,H,P,A>::key_eq() const
- {
- return table_.key_eq();
- }
+template <class T, class H, class P, class A>
+typename unordered_set<T, H, P, A>::key_equal
+unordered_set<T, H, P, A>::key_eq() const
+{
+ return table_.key_eq();
+}
- // lookup
+template <class T, class H, class P, class A>
+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_);
+}
- template <class T, class H, class P, class A>
- typename unordered_set<T,H,P,A>::const_iterator
- unordered_set<T,H,P,A>::find(const key_type& k) const
- {
- return const_iterator(table_.find_node(k));
- }
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+template <class T, class H, class P, class A>
+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_);
+}
+#endif
- template <class T, class H, class P, class A>
- template <class CompatibleKey, class CompatibleHash,
- class CompatiblePredicate>
- 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));
- }
+#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_);
+}
- 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);
- }
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+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_);
+}
+#endif
+#endif
- template <class T, class H, class P, class A>
- 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);
- }
+// lookup
- template <class T, class H, class P, class A>
- typename unordered_set<T,H,P,A>::size_type
- unordered_set<T,H,P,A>::bucket_size(size_type n) const
- {
- return table_.bucket_size(n);
- }
+template <class T, class H, class P, class A>
+typename unordered_set<T, H, P, A>::const_iterator
+unordered_set<T, H, P, A>::find(const key_type& k) const
+{
+ return const_iterator(table_.find_node(k));
+}
+
+template <class T, class H, class P, class A>
+template <class CompatibleKey, class CompatibleHash, class CompatiblePredicate>
+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));
+}
- // hash policy
+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);
+}
- 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();
- }
+template <class T, class H, class P, class A>
+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);
+}
- template <class T, class H, class P, class A>
- void unordered_set<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
- {
- table_.max_load_factor(m);
- }
+template <class T, class H, class P, class A>
+typename unordered_set<T, H, P, A>::size_type
+unordered_set<T, H, P, A>::bucket_size(size_type n) const
+{
+ return table_.bucket_size(n);
+}
- template <class T, class H, class P, class A>
- void unordered_set<T,H,P,A>::rehash(size_type n)
- {
- table_.rehash(n);
- }
+// hash policy
- template <class T, class H, class P, class A>
- void unordered_set<T,H,P,A>::reserve(size_type n)
- {
- table_.reserve(n);
- }
+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();
+}
- template <class T, class H, class P, class A>
- inline bool operator==(
- unordered_set<T,H,P,A> const& m1,
- unordered_set<T,H,P,A> const& m2)
- {
+template <class T, class H, class P, class A>
+void unordered_set<T, H, P, A>::max_load_factor(float m) BOOST_NOEXCEPT
+{
+ table_.max_load_factor(m);
+}
+
+template <class T, class H, class P, class A>
+void unordered_set<T, H, P, A>::rehash(size_type n)
+{
+ table_.rehash(n);
+}
+
+template <class T, class H, class P, class A>
+void unordered_set<T, H, P, A>::reserve(size_type n)
+{
+ table_.reserve(n);
+}
+
+template <class T, class H, class P, class A>
+inline bool operator==(
+ unordered_set<T, H, P, A> const& m1, unordered_set<T, H, P, A> const& m2)
+{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { unordered_set<T,H,P,A> x; };
+ struct dummy
+ {
+ unordered_set<T, H, P, A> x;
+ };
#endif
- return m1.table_.equals(m2.table_);
- }
+ return m1.table_.equals(m2.table_);
+}
- template <class T, class H, class P, class A>
- inline bool operator!=(
- unordered_set<T,H,P,A> const& m1,
- unordered_set<T,H,P,A> const& m2)
- {
+template <class T, class H, class P, class A>
+inline bool operator!=(
+ unordered_set<T, H, P, A> const& m1, unordered_set<T, H, P, A> const& m2)
+{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { unordered_set<T,H,P,A> x; };
+ struct dummy
+ {
+ unordered_set<T, H, P, A> x;
+ };
#endif
- return !m1.table_.equals(m2.table_);
- }
+ return !m1.table_.equals(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)
- {
+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)
+{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { unordered_set<T,H,P,A> x; };
+ struct dummy
+ {
+ unordered_set<T, H, P, A> x;
+ };
#endif
- m1.swap(m2);
- }
+ m1.swap(m2);
+}
////////////////////////////////////////////////////////////////////////////////
- template <class T, class H, class P, class A>
- unordered_multiset<T,H,P,A>::unordered_multiset()
- : table_(boost::unordered::detail::default_bucket_count, hasher(),
- key_equal(), allocator_type())
- {
- }
+template <class T, class H, class P, class A>
+unordered_multiset<T, H, P, A>::unordered_multiset()
+ : table_(boost::unordered::detail::default_bucket_count, hasher(),
+ key_equal(), allocator_type())
+{
+}
- template <class T, class H, class P, class A>
- unordered_multiset<T,H,P,A>::unordered_multiset(
- size_type n, const hasher &hf, const key_equal &eql,
- const allocator_type &a)
- : table_(n, hf, eql, a)
- {
- }
+template <class T, class H, class P, class A>
+unordered_multiset<T, H, P, A>::unordered_multiset(size_type n,
+ const hasher& hf, const key_equal& eql, const allocator_type& a)
+ : table_(n, hf, eql, a)
+{
+}
- 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 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 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)
- {
- }
+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)
+{
+}
- template <class T, class H, class P, class A>
- unordered_multiset<T,H,P,A>::unordered_multiset(allocator_type const& a)
- : table_(boost::unordered::detail::default_bucket_count,
- hasher(), key_equal(), a)
- {
- }
+template <class T, class H, class P, class A>
+unordered_multiset<T, H, P, A>::unordered_multiset(allocator_type const& a)
+ : table_(boost::unordered::detail::default_bucket_count, hasher(),
+ key_equal(), a)
+{
+}
- template <class T, class H, class P, class A>
- unordered_multiset<T,H,P,A>::unordered_multiset(
- unordered_multiset const& other, allocator_type const& a)
- : table_(other.table_, a)
- {
- }
+template <class T, class H, class P, class A>
+unordered_multiset<T, H, P, A>::unordered_multiset(
+ unordered_multiset const& other, allocator_type const& a)
+ : table_(other.table_, a)
+{
+}
- 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())
- {
- 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)
+ : table_(boost::unordered::detail::initial_size(f, l), hasher(),
+ key_equal(), allocator_type())
+{
+ 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, size_type n, const hasher& hf, const key_equal& eql)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql,
+ allocator_type())
+{
+ 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,
+ 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)
+{
+ 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,
+ size_type n, const hasher& hf, const allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(f, l, n), hf, 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, size_type n, const allocator_type& a)
+ : 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>
- 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())
- {
- 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,
- 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)
- {
- 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,
- size_type n,
- const hasher &hf,
- const allocator_type &a)
- : table_(boost::unordered::detail::initial_size(f, l, n),
- hf, 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
+{
+}
- 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 allocator_type &a)
- : 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(
+ 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_NOEXCEPT {}
+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 T, class H, class P, class A>
- unordered_multiset<T,H,P,A>::unordered_multiset(
- unordered_multiset const& other)
- : table_(other.table_)
- {
- }
+#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(
- BOOST_RV_REF(unordered_multiset) other, allocator_type const& a)
- : table_(other.table_, a, boost::unordered::detail::move_tag())
- {
- }
+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)
+ : table_(
+ boost::unordered::detail::initial_size(list.begin(), list.end(), n),
+ hf, eql, a)
+{
+ table_.insert_range(list.begin(), list.end());
+}
+
+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 allocator_type& a)
+ : table_(
+ boost::unordered::detail::initial_size(list.begin(), list.end(), n),
+ hf, key_equal(), a)
+{
+ table_.insert_range(list.begin(), list.end());
+}
+
+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)
+{
+ 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());
+ return *this;
+}
- 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)
- : table_(
- boost::unordered::detail::initial_size(
- list.begin(), list.end(), n),
- hf, eql, a)
- {
- table_.insert_range(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 hasher &hf, const allocator_type &a)
- : table_(
- boost::unordered::detail::initial_size(
- list.begin(), list.end(), n),
- hf, key_equal(), a)
- {
- table_.insert_range(list.begin(), list.end());
- }
+// size and capacity
- 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)
- {
- table_.insert_range(list.begin(), list.end());
- }
+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();
+}
- 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());
- return *this;
- }
+// modifiers
+
+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);
+}
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+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());
+}
#endif
- // size and capacity
+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);
+}
- 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();
- }
+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);
+}
- // modifiers
+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>
- template <class InputIt>
- void unordered_multiset<T,H,P,A>::insert(InputIt first, InputIt last)
- {
- table_.insert_range(first, last);
+template <class T, class H, class P, class A>
+void unordered_multiset<T, H, P, A>::clear()
+{
+ table_.clear();
+}
+
+template <class T, class H, class P, class A>
+void unordered_multiset<T, H, P, A>::swap(unordered_multiset& other)
+{
+ table_.swap(other.table_);
+}
+
+// observers
+
+template <class T, class H, class P, class A>
+typename unordered_multiset<T, H, P, A>::hasher
+unordered_multiset<T, H, P, A>::hash_function() const
+{
+ return table_.hash_function();
+}
+
+template <class T, class H, class P, class A>
+typename unordered_multiset<T, H, P, A>::key_equal
+unordered_multiset<T, H, P, A>::key_eq() const
+{
+ return table_.key_eq();
+}
+
+template <class T, class H, class P, class A>
+template <typename H2, typename P2>
+void unordered_multiset<T, H, P, A>::merge(
+ boost::unordered_multiset<T, H2, P2, A>& source)
+{
+ while (!source.empty()) {
+ insert(source.extract(source.begin()));
}
+}
-#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- 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());
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+template <class T, class H, class P, class A>
+template <typename H2, typename P2>
+void unordered_multiset<T, H, P, A>::merge(
+ boost::unordered_multiset<T, H2, P2, A>&& source)
+{
+ while (!source.empty()) {
+ insert(source.extract(source.begin()));
}
+}
#endif
- 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);
+#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(
+ boost::unordered_set<T, H2, P2, A>& source)
+{
+ while (!source.empty()) {
+ insert(source.extract(source.begin()));
}
+}
- 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);
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+template <class T, class H, class P, class A>
+template <typename H2, typename P2>
+void unordered_multiset<T, H, P, A>::merge(
+ boost::unordered_set<T, H2, P2, A>&& source)
+{
+ while (!source.empty()) {
+ insert(source.extract(source.begin()));
}
+}
+#endif
+#endif
+
+// lookup
+
+template <class T, class H, class P, class A>
+typename unordered_multiset<T, H, P, A>::const_iterator
+unordered_multiset<T, H, P, A>::find(const key_type& k) const
+{
+ return const_iterator(table_.find_node(k));
+}
+
+template <class T, class H, class P, class A>
+template <class CompatibleKey, class CompatibleHash, class CompatiblePredicate>
+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));
+}
+
+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);
+}
- 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)
+template <class T, class H, class P, class A>
+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);
+}
+
+template <class T, class H, class P, class A>
+typename unordered_multiset<T, H, P, A>::size_type
+unordered_multiset<T, H, P, A>::bucket_size(size_type n) const
+{
+ return table_.bucket_size(n);
+}
+
+// hash policy
+
+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();
+}
+
+template <class T, class H, class P, class A>
+void unordered_multiset<T, H, P, A>::max_load_factor(float m) BOOST_NOEXCEPT
+{
+ table_.max_load_factor(m);
+}
+
+template <class T, class H, class P, class A>
+void unordered_multiset<T, H, P, A>::rehash(size_type n)
+{
+ table_.rehash(n);
+}
+
+template <class T, class H, class P, class A>
+void unordered_multiset<T, H, P, A>::reserve(size_type n)
+{
+ table_.reserve(n);
+}
+
+template <class T, class H, class P, class A>
+inline bool operator==(unordered_multiset<T, H, P, A> const& m1,
+ unordered_multiset<T, H, P, A> const& m2)
+{
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+ struct dummy
{
- return table_.erase_range(first, last);
- }
+ unordered_multiset<T, H, P, A> x;
+ };
+#endif
+ return m1.table_.equals(m2.table_);
+}
- template <class T, class H, class P, class A>
- void unordered_multiset<T,H,P,A>::clear()
+template <class T, class H, class P, class A>
+inline bool operator!=(unordered_multiset<T, H, P, A> const& m1,
+ unordered_multiset<T, H, P, A> const& m2)
+{
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+ struct dummy
{
- table_.clear();
- }
+ unordered_multiset<T, H, P, A> x;
+ };
+#endif
+ return !m1.table_.equals(m2.table_);
+}
- template <class T, class H, class P, class A>
- void unordered_multiset<T,H,P,A>::swap(unordered_multiset& other)
+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)
+{
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+ struct dummy
{
- table_.swap(other.table_);
- }
+ unordered_multiset<T, H, P, A> x;
+ };
+#endif
+ m1.swap(m2);
+}
- // observers
+template <typename N, typename T, typename A> class node_handle_set
+{
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle_set)
- template <class T, class H, class P, class A>
- typename unordered_multiset<T,H,P,A>::hasher
- unordered_multiset<T,H,P,A>::hash_function() const
- {
- return table_.hash_function();
- }
+ template <typename Types>
+ friend struct ::boost::unordered::detail::table_impl;
+ template <typename Types>
+ friend struct ::boost::unordered::detail::grouped_table_impl;
- template <class T, class H, class P, class A>
- typename unordered_multiset<T,H,P,A>::key_equal
- unordered_multiset<T,H,P,A>::key_eq() const
- {
- return table_.key_eq();
- }
+ typedef typename boost::unordered::detail::rebind_wrap<A, T>::type
+ value_allocator;
+ typedef boost::unordered::detail::allocator_traits<value_allocator>
+ value_allocator_traits;
+ typedef N node;
+ typedef typename boost::unordered::detail::rebind_wrap<A, node>::type
+ node_allocator;
+ typedef boost::unordered::detail::allocator_traits<node_allocator>
+ node_allocator_traits;
+ typedef typename node_allocator_traits::pointer node_pointer;
- // lookup
+ public:
+ typedef T value_type;
+ typedef A allocator_type;
+
+ private:
+ node_pointer ptr_;
+ bool has_alloc_;
+ boost::unordered::detail::value_base<value_allocator> alloc_;
- template <class T, class H, class P, class A>
- typename unordered_multiset<T,H,P,A>::const_iterator
- unordered_multiset<T,H,P,A>::find(const key_type& k) const
+ public:
+ BOOST_CONSTEXPR node_handle_set() BOOST_NOEXCEPT : ptr_(), has_alloc_(false)
{
- return const_iterator(table_.find_node(k));
}
- template <class T, class H, class P, class A>
- template <class CompatibleKey, class CompatibleHash,
- class CompatiblePredicate>
- 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
+ /*BOOST_CONSTEXPR */ node_handle_set(
+ node_pointer ptr, allocator_type const& a)
+ : ptr_(ptr), has_alloc_(false)
{
- return const_iterator(table_.generic_find_node(k, hash, eq));
+ if (ptr_) {
+ new ((void*)&alloc_) value_allocator(a);
+ has_alloc_ = true;
+ }
}
- 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
+ ~node_handle_set()
{
- return table_.count(k);
+ if (has_alloc_ && ptr_) {
+ node_allocator node_alloc(alloc_.value());
+ boost::unordered::detail::node_tmp<node_allocator> tmp(
+ ptr_, node_alloc);
+ }
+ if (has_alloc_) {
+ alloc_.value_ptr()->~value_allocator();
+ }
}
- template <class T, class H, class P, class A>
- 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
+ node_handle_set(BOOST_RV_REF(node_handle_set) n) BOOST_NOEXCEPT
+ : ptr_(n.ptr_),
+ has_alloc_(false)
{
- return table_.equal_range(k);
+ if (n.has_alloc_) {
+ new ((void*)&alloc_) value_allocator(boost::move(n.alloc_.value()));
+ has_alloc_ = true;
+ n.ptr_ = node_pointer();
+ n.alloc_.value_ptr()->~value_allocator();
+ n.has_alloc_ = false;
+ }
}
- template <class T, class H, class P, class A>
- typename unordered_multiset<T,H,P,A>::size_type
- unordered_multiset<T,H,P,A>::bucket_size(size_type n) const
+ node_handle_set& operator=(BOOST_RV_REF(node_handle_set) n)
{
- return table_.bucket_size(n);
- }
+ BOOST_ASSERT(!has_alloc_ ||
+ value_allocator_traits::
+ propagate_on_container_move_assignment::value ||
+ (n.has_alloc_ && alloc_.value() == n.alloc_.value()));
- // hash policy
+ if (ptr_) {
+ node_allocator node_alloc(alloc_.value());
+ boost::unordered::detail::node_tmp<node_allocator> tmp(
+ ptr_, node_alloc);
+ ptr_ = node_pointer();
+ }
- 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();
- }
+ if (has_alloc_) {
+ alloc_.value_ptr()->~value_allocator();
+ has_alloc_ = false;
+ }
- template <class T, class H, class P, class A>
- void unordered_multiset<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
- {
- table_.max_load_factor(m);
+ if (!has_alloc_ && n.has_alloc_) {
+ move_allocator(n);
+ }
+
+ ptr_ = n.ptr_;
+ n.ptr_ = node_pointer();
+
+ return *this;
}
- template <class T, class H, class P, class A>
- void unordered_multiset<T,H,P,A>::rehash(size_type n)
+ value_type& value() const { return ptr_->value(); }
+
+ allocator_type get_allocator() const { return alloc_.value(); }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ bool operator!() const BOOST_NOEXCEPT { return ptr_ ? 0 : 1; }
+
+ bool empty() const BOOST_NOEXCEPT { return ptr_ ? 0 : 1; }
+
+ void swap(node_handle_set& n) BOOST_NOEXCEPT_IF(
+ value_allocator_traits::propagate_on_container_swap::value
+ /* || value_allocator_traits::is_always_equal::value */)
{
- table_.rehash(n);
+ if (!has_alloc_) {
+ if (n.has_alloc_) {
+ move_allocator(n);
+ }
+ } else if (!n.has_alloc_) {
+ n.move_allocator(*this);
+ } else {
+ swap_impl(n, boost::unordered::detail::integral_constant<bool,
+ value_allocator_traits::
+ propagate_on_container_swap::value>());
+ }
+ boost::swap(ptr_, n.ptr_);
}
- template <class T, class H, class P, class A>
- void unordered_multiset<T,H,P,A>::reserve(size_type n)
+ private:
+ void move_allocator(node_handle_set& n)
{
- table_.reserve(n);
+ new ((void*)&alloc_) value_allocator(boost::move(n.alloc_.value()));
+ n.alloc_.value_ptr()->~value_allocator();
+ has_alloc_ = true;
+ n.has_alloc_ = false;
}
- template <class T, class H, class P, class A>
- inline bool operator==(
- unordered_multiset<T,H,P,A> const& m1,
- unordered_multiset<T,H,P,A> const& m2)
+ void swap_impl(node_handle_set&, boost::unordered::detail::false_type) {}
+
+ void swap_impl(node_handle_set& n, boost::unordered::detail::true_type)
{
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { unordered_multiset<T,H,P,A> x; };
-#endif
- return m1.table_.equals(m2.table_);
+ boost::swap(alloc_, n.alloc_);
}
+};
+
+template <typename N, typename T, typename A>
+void swap(node_handle_set<N, T, A>& x, node_handle_set<N, T, A>& y)
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(x.swap(y)))
+{
+ x.swap(y);
+}
+
+template <typename N, typename T, typename A> struct insert_return_type_set
+{
+ private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_set)
+
+ typedef typename boost::unordered::detail::rebind_wrap<A, T>::type
+ value_allocator;
+ typedef N node_;
- template <class T, class H, class P, class A>
- inline bool operator!=(
- unordered_multiset<T,H,P,A> const& m1,
- unordered_multiset<T,H,P,A> const& m2)
+ public:
+ bool inserted;
+ boost::unordered::iterator_detail::c_iterator<node_> position;
+ boost::unordered::node_handle_set<N, T, A> node;
+
+ insert_return_type_set() : inserted(false), position(), node() {}
+
+ insert_return_type_set(BOOST_RV_REF(insert_return_type_set)
+ x) BOOST_NOEXCEPT : inserted(x.inserted),
+ position(x.position),
+ node(boost::move(x.node))
{
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { unordered_multiset<T,H,P,A> x; };
-#endif
- return !m1.table_.equals(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)
+ insert_return_type_set& operator=(BOOST_RV_REF(insert_return_type_set) x)
{
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { unordered_multiset<T,H,P,A> x; };
-#endif
- m1.swap(m2);
+ inserted = x.inserted;
+ position = x.position;
+ node = boost::move(x.node);
+ return *this;
}
+};
+
+template <typename N, typename T, typename A>
+void swap(
+ insert_return_type_set<N, T, A>& x, insert_return_type_set<N, T, A>& y)
+{
+ boost::swap(x.node, y.node);
+ boost::swap(x.inserted, y.inserted);
+ boost::swap(x.position, y.position);
+}
} // namespace unordered
} // namespace boost
diff --git a/boost/unordered/unordered_set_fwd.hpp b/boost/unordered/unordered_set_fwd.hpp
index 52b9e822f2..d3a3b51e74 100644
--- a/boost/unordered/unordered_set_fwd.hpp
+++ b/boost/unordered/unordered_set_fwd.hpp
@@ -11,53 +11,49 @@
#pragma once
#endif
-#include <memory>
-#include <functional>
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
+#include <functional>
+#include <memory>
+
+namespace boost {
+namespace unordered {
+template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
+ class A = std::allocator<T> >
+class unordered_set;
+
+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 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);
+
+template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
+ class A = std::allocator<T> >
+class unordered_multiset;
+
+template <class T, class H, class P, class A>
+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 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);
+
+template <class N, class T, class A> class node_handle_set;
+template <class N, class T, class A> struct insert_return_type_set;
+}
-namespace boost
-{
- namespace unordered
- {
- template <class T,
- class H = boost::hash<T>,
- class P = std::equal_to<T>,
- class A = std::allocator<T> >
- class unordered_set;
-
- 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 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);
-
- template <class T,
- class H = boost::hash<T>,
- class P = std::equal_to<T>,
- class A = std::allocator<T> >
- class unordered_multiset;
-
- template <class T, class H, class P, class A>
- 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 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);
- }
-
- using boost::unordered::unordered_set;
- using boost::unordered::unordered_multiset;
- using boost::unordered::swap;
- using boost::unordered::operator==;
- using boost::unordered::operator!=;
+using boost::unordered::unordered_set;
+using boost::unordered::unordered_multiset;
+using boost::unordered::swap;
+using boost::unordered::operator==;
+using boost::unordered::operator!=;
}
#endif
diff --git a/boost/utility.hpp b/boost/utility.hpp
index 82177c8b47..0aacb8bc36 100644
--- a/boost/utility.hpp
+++ b/boost/utility.hpp
@@ -14,8 +14,8 @@
#include <boost/utility/binary.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/utility/identity_type.hpp>
-#include <boost/checked_delete.hpp>
+#include <boost/core/checked_delete.hpp>
+#include <boost/core/noncopyable.hpp>
#include <boost/next_prior.hpp>
-#include <boost/noncopyable.hpp>
#endif // BOOST_UTILITY_HPP
diff --git a/boost/utility/string_ref.hpp b/boost/utility/string_ref.hpp
index 5acf346fba..d234e5444a 100644
--- a/boost/utility/string_ref.hpp
+++ b/boost/utility/string_ref.hpp
@@ -92,6 +92,13 @@ namespace boost {
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str)
: ptr_(str.data()), len_(str.length()) {}
+// #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+// // Constructing a string_ref from a temporary string is a bad idea
+// template<typename Allocator>
+// basic_string_ref( std::basic_string<charT, traits, Allocator>&&)
+// = delete;
+// #endif
+
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len) BOOST_NOEXCEPT
: ptr_(str), len_(len) {}
@@ -155,9 +162,7 @@ namespace boost {
basic_string_ref substr(size_type pos, size_type n=npos) const {
if ( pos > size())
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_ref::substr" ) );
- if ( n == npos || pos + n > size())
- n = size () - pos;
- return basic_string_ref ( data() + pos, n );
+ return basic_string_ref(data() + pos, (std::min)(size() - pos, n));
}
int compare(basic_string_ref x) const {
diff --git a/boost/utility/string_view.hpp b/boost/utility/string_view.hpp
index 167b30c16c..425d7d2de3 100644
--- a/boost/utility/string_view.hpp
+++ b/boost/utility/string_view.hpp
@@ -91,9 +91,15 @@ namespace boost {
#endif
template<typename Allocator>
- basic_string_view(const std::basic_string<charT, traits,
- Allocator>& str) BOOST_NOEXCEPT
- : ptr_(str.data()), len_(str.length()) {}
+ basic_string_view(const std::basic_string<charT, traits, Allocator>& str) BOOST_NOEXCEPT
+ : ptr_(str.data()), len_(str.length()) {}
+
+// #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+// // Constructing a string_view from a temporary string is a bad idea
+// template<typename Allocator>
+// basic_string_view( std::basic_string<charT, traits, Allocator>&&)
+// = delete;
+// #endif
BOOST_CONSTEXPR basic_string_view(const charT* str)
: ptr_(str), len_(traits::length(str)) {}
@@ -121,10 +127,7 @@ namespace boost {
BOOST_CONSTEXPR const_reference operator[](size_type pos) const BOOST_NOEXCEPT { return ptr_[pos]; }
BOOST_CONSTEXPR const_reference at(size_t pos) const {
- return pos >= len_ ? BOOST_THROW_EXCEPTION(std::out_of_range("boost::string_view::at")) : ptr_[pos];
-// if ( pos >= len_ )
-// BOOST_THROW_EXCEPTION( std::out_of_range ( "boost::string_view::at" ) );
-// return ptr_[pos];
+ return pos >= len_ ? BOOST_THROW_EXCEPTION(std::out_of_range("boost::string_view::at")), ptr_[0] : ptr_[pos];
}
BOOST_CONSTEXPR const_reference front() const { return ptr_[0]; }
@@ -180,18 +183,14 @@ namespace boost {
if (pos > size())
BOOST_THROW_EXCEPTION(std::out_of_range("string_view::copy" ));
size_type rlen = (std::min)(n, len_ - pos);
- // use std::copy(begin() + pos, begin() + pos + rlen, s) rather than
- // std::copy_n(begin() + pos, rlen, s) to support pre-C++11 standard libraries
- std::copy(begin() + pos, begin() + pos + rlen, s);
+ traits_type::copy(s, data() + pos, rlen);
return rlen;
}
BOOST_CXX14_CONSTEXPR basic_string_view substr(size_type pos, size_type n=npos) const {
if ( pos > size())
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_view::substr" ) );
- if (n == npos || pos + n > size())
- n = size () - pos;
- return basic_string_view(data() + pos, n);
+ return basic_string_view(data() + pos, (std::min)(size() - pos, n));
}
BOOST_CXX14_CONSTEXPR int compare(basic_string_view x) const BOOST_NOEXCEPT {
diff --git a/boost/variant/polymorphic_get.hpp b/boost/variant/polymorphic_get.hpp
index 89fca36de7..1a98382be6 100644
--- a/boost/variant/polymorphic_get.hpp
+++ b/boost/variant/polymorphic_get.hpp
@@ -3,7 +3,7 @@
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
-// Copyright (c) 2013-2015 Antony Polukhin
+// Copyright (c) 2013-2017 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -113,13 +113,15 @@ public: // visitor interfaces
template <typename U>
pointer operator()(U& operand) const BOOST_NOEXCEPT
{
+ typedef typename boost::remove_reference<Base>::type base_t;
typedef boost::integral_constant<
bool,
- boost::mpl::or_<
- boost::is_base_of<Base, U>,
- boost::is_same<Base, U>,
- boost::is_same<typename boost::remove_cv<Base>::type, U >
- >::value
+ (
+ boost::is_base_of<base_t, U>::value &&
+ (boost::is_const<base_t>::value || !boost::is_const<U>::value)
+ )
+ || boost::is_same<base_t, U>::value
+ || boost::is_same<typename boost::remove_cv<base_t>::type, U >::value
> tag_t;
return this_type::get(operand, tag_t());
diff --git a/boost/variant/recursive_wrapper_fwd.hpp b/boost/variant/recursive_wrapper_fwd.hpp
index 2fc4341262..c40399f289 100644
--- a/boost/variant/recursive_wrapper_fwd.hpp
+++ b/boost/variant/recursive_wrapper_fwd.hpp
@@ -4,7 +4,7 @@
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002 Eric Friedman, Itay Maman
-// Copyright (c) 2016 Antony Polukhin
+// Copyright (c) 2016-2017 Antony Polukhin
//
// Portions Copyright (C) 2002 David Abrahams
//
@@ -20,6 +20,7 @@
#include <boost/mpl/aux_/lambda_support.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_constructible.hpp>
+#include <boost/type_traits/is_nothrow_move_constructible.hpp>
namespace boost {
@@ -65,6 +66,9 @@ template <class T, class U> struct is_constructible<recursive_wrapper<T>, const
template <class T, class U> struct is_constructible<recursive_wrapper<T>, recursive_wrapper<U>& > : boost::false_type{};
template <class T, class U> struct is_constructible<recursive_wrapper<T>, const recursive_wrapper<U>& > : boost::false_type{};
+// recursive_wrapper is not nothrow move constructible, because it's constructor does dynamic memory allocation.
+// This specialisation is required to workaround GCC6 issue: https://svn.boost.org/trac/boost/ticket/12680
+template <class T> struct is_nothrow_move_constructible<recursive_wrapper<T> > : boost::false_type{};
///////////////////////////////////////////////////////////////////////////////
// metafunction is_recursive_wrapper (modeled on code by David Abrahams)
diff --git a/boost/variant/variant.hpp b/boost/variant/variant.hpp
index 6296238507..1c64447428 100644
--- a/boost/variant/variant.hpp
+++ b/boost/variant/variant.hpp
@@ -1756,10 +1756,12 @@ public: // structors, cont.
template <typename T>
variant(const T& operand,
- typename boost::enable_if<mpl::and_<
- mpl::not_< boost::is_same<T, variant> >,
- boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
- > >::type* = 0)
+ typename boost::enable_if<mpl::or_<
+ mpl::and_<
+ mpl::not_< boost::is_same<T, variant> >,
+ boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
+ >,
+ boost::is_same<T, boost::recursive_variant_> > >::type* = 0)
{
convert_construct(operand, 1L);
}
@@ -1767,11 +1769,13 @@ public: // structors, cont.
template <typename T>
variant(
T& operand
- , typename boost::enable_if<mpl::and_<
- mpl::not_< is_const<T> >,
- mpl::not_< boost::is_same<T, variant> >,
- boost::detail::variant::is_variant_constructible_from<T&, internal_types>
- > >::type* = 0
+ , typename boost::enable_if<mpl::or_<
+ mpl::and_<
+ mpl::not_< is_const<T> >,
+ mpl::not_< boost::is_same<T, variant> >,
+ boost::detail::variant::is_variant_constructible_from<T&, internal_types>
+ >,
+ boost::is_same<T, boost::recursive_variant_> > >::type* = 0
)
{
convert_construct(operand, 1L);
@@ -1780,12 +1784,14 @@ public: // structors, cont.
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class T>
variant(T&& operand,
- typename boost::enable_if<mpl::and_<
- boost::is_rvalue_reference<T&&>,
- mpl::not_< boost::is_const<T> >,
- mpl::not_< boost::is_same<T, variant> >,
- boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
- > >::type* = 0)
+ typename boost::enable_if<mpl::or_<
+ mpl::and_<
+ boost::is_rvalue_reference<T&&>,
+ mpl::not_< boost::is_const<T> >,
+ mpl::not_< boost::is_same<T, variant> >,
+ boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
+ >,
+ boost::is_same<T, boost::recursive_variant_> > >::type* = 0)
{
convert_construct( detail::variant::move(operand), 1L);
}
diff --git a/boost/variant/variant_fwd.hpp b/boost/variant/variant_fwd.hpp
index 769ecc4e54..b533f76668 100644
--- a/boost/variant/variant_fwd.hpp
+++ b/boost/variant/variant_fwd.hpp
@@ -59,7 +59,7 @@
GCC before 4.0 had no variadic tempaltes;
GCC 4.6 has incomplete implementation of variadic templates.
- MSVC2013 has variadic templates, but they have issues.
+ MSVC2015 Update 1 has variadic templates, but they have issues.
NOTE: Clang compiler defines __GNUC__
*/
diff --git a/boost/version.hpp b/boost/version.hpp
index 94c16c31c3..03b33f9ae0 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 106300
+#define BOOST_VERSION 106400
//
// 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_63"
+#define BOOST_LIB_VERSION "1_64"
#endif